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 91cfe4df8fa4730c86caa3a5cd7bb958d839ad02..9c47e6beb58b44b9ecfc39e130a5cec136a387cc 100644 |
| --- a/src/interpreter/bytecode-array-builder.cc |
| +++ b/src/interpreter/bytecode-array-builder.cc |
| @@ -8,7 +8,7 @@ namespace v8 { |
| namespace internal { |
| namespace interpreter { |
| -class BytecodeArrayBuilder::PreviousBytecodeHelper { |
| +class BytecodeArrayBuilder::PreviousBytecodeHelper BASE_EMBEDDED { |
| public: |
| explicit PreviousBytecodeHelper(const BytecodeArrayBuilder& array_builder) |
| : array_builder_(array_builder), |
| @@ -37,9 +37,9 @@ class BytecodeArrayBuilder::PreviousBytecodeHelper { |
| Bytecodes::GetOperandOffset(bytecode, operand_index); |
| OperandSize size = Bytecodes::GetOperandSize(bytecode, operand_index); |
| switch (size) { |
| - default: |
| case OperandSize::kNone: |
| UNREACHABLE(); |
| + break; |
| case OperandSize::kByte: |
| return static_cast<uint32_t>( |
| array_builder_.bytecodes()->at(operand_offset)); |
| @@ -49,6 +49,7 @@ class BytecodeArrayBuilder::PreviousBytecodeHelper { |
| array_builder_.bytecodes()->at(operand_offset + 1); |
| return static_cast<uint32_t>(operand); |
| } |
| + return 0; |
| } |
| Handle<Object> GetConstantForIndexOperand(int operand_index) const { |
| @@ -64,6 +65,39 @@ class BytecodeArrayBuilder::PreviousBytecodeHelper { |
| }; |
| +class BytecodeArrayBuilder::RegisterTranslationScope BASE_EMBEDDED { |
| + public: |
| + static const Bytecode kInvalidBytecode = static_cast<Bytecode>(-1); |
| + |
| + RegisterTranslationScope(BytecodeArrayBuilder* builder, |
| + Bytecode bytecode = kInvalidBytecode) |
| + : builder_(builder), bytecode_(bytecode) { |
| + builder->set_register_translation_scope(this); |
|
rmcilroy
2016/01/22 17:50:56
DCHECK_EQ(nullptr, builder()->register_translation
|
| + } |
| + |
| + ~RegisterTranslationScope() { |
| + translator()->CompleteTranslations(); |
| + builder()->set_register_translation_scope(nullptr); |
| + } |
| + |
| + Register Translate(Register reg) { |
| + return translator()->Translate(bytecode(), reg); |
| + } |
| + |
| + void set_bytecode(Bytecode bytecode) { bytecode_ = bytecode; } |
| + Bytecode bytecode() const { return bytecode_; } |
| + |
| + private: |
| + BytecodeArrayBuilder* builder() const { return builder_; } |
| + RegisterTranslator* translator() { return builder()->register_translator(); } |
| + |
| + BytecodeArrayBuilder* builder_; |
| + Bytecode bytecode_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(RegisterTranslationScope); |
| +}; |
| + |
| + |
| BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone) |
| : isolate_(isolate), |
| zone_(zone), |
| @@ -79,7 +113,9 @@ BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone) |
| local_register_count_(-1), |
| context_register_count_(-1), |
| temporary_register_count_(0), |
| - free_temporaries_(zone) {} |
| + free_temporaries_(zone), |
| + register_translator_(this), |
| + register_translation_scope_(nullptr) {} |
| BytecodeArrayBuilder::~BytecodeArrayBuilder() { DCHECK_EQ(0, unbound_jumps_); } |
| @@ -148,7 +184,8 @@ Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() { |
| EnsureReturn(); |
| int bytecode_size = static_cast<int>(bytecodes_.size()); |
| - int register_count = fixed_register_count() + temporary_register_count_; |
| + int register_count = |
| + fixed_and_temporary_register_count() + translation_register_count(); |
| int frame_size = register_count * kPointerSize; |
| Handle<FixedArray> constant_pool = constant_array_builder()->ToFixedArray(); |
| Handle<FixedArray> handler_table = handler_table_builder()->ToHandlerTable(); |
| @@ -167,6 +204,13 @@ void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t(&operands)[N]) { |
| if (exit_seen_in_block_) return; |
| DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), static_cast<int>(N)); |
| + DCHECK((register_translation_scope() == nullptr && |
| + Bytecodes::NumberOfRegisterOperands(bytecode) == 0) || |
| + (register_translation_scope() != nullptr && |
| + Bytecodes::NumberOfRegisterOperands(bytecode) > 0)); |
| + DCHECK(register_translator()->RegisterOperandsValid(bytecode, operands, |
| + static_cast<int>(N))); |
| + |
| last_bytecode_start_ = bytecodes()->size(); |
| bytecodes()->push_back(Bytecodes::ToByte(bytecode)); |
| for (int i = 0; i < static_cast<int>(N); i++) { |
| @@ -174,6 +218,7 @@ void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t(&operands)[N]) { |
| switch (Bytecodes::GetOperandSize(bytecode, i)) { |
| case OperandSize::kNone: |
| UNREACHABLE(); |
| + break; |
| case OperandSize::kByte: |
| bytecodes()->push_back(static_cast<uint8_t>(operands[i])); |
| break; |
| @@ -234,7 +279,9 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, |
| UNIMPLEMENTED(); |
| } |
| - Output(BytecodeForBinaryOperation(op), reg.ToRawOperand()); |
| + RegisterTranslationScope translator(this, BytecodeForBinaryOperation(op)); |
| + reg = translator.Translate(reg); |
| + Output(translator.bytecode(), reg.ToRawOperand()); |
|
rmcilroy
2016/01/22 17:50:56
To avoid the extra translate call, could we write
|
| return *this; |
| } |
| @@ -268,7 +315,9 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation( |
| UNIMPLEMENTED(); |
| } |
| - Output(BytecodeForCompareOperation(op), reg.ToRawOperand()); |
| + RegisterTranslationScope translator(this, BytecodeForCompareOperation(op)); |
| + reg = translator.Translate(reg); |
| + Output(translator.bytecode(), reg.ToRawOperand()); |
| return *this; |
| } |
| @@ -342,8 +391,10 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadBooleanConstant(bool value) { |
| BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister( |
| Register reg) { |
| + RegisterTranslationScope translator(this, Bytecode::kLdar); |
| + reg = translator.Translate(reg); |
| if (!IsRegisterInAccumulator(reg)) { |
| - Output(Bytecode::kLdar, reg.ToRawOperand()); |
| + Output(translator.bytecode(), reg.ToRawOperand()); |
| } |
| return *this; |
| } |
| @@ -351,8 +402,10 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister( |
| BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister( |
| Register reg) { |
| + RegisterTranslationScope translator(this, Bytecode::kStar); |
| + reg = translator.Translate(reg); |
| if (!IsRegisterInAccumulator(reg)) { |
| - Output(Bytecode::kStar, reg.ToRawOperand()); |
| + Output(translator.bytecode(), reg.ToRawOperand()); |
| } |
| return *this; |
| } |
| @@ -361,17 +414,42 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister( |
| BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, |
| Register to) { |
| DCHECK(from != to); |
| - if (FitsInReg8Operand(to) && FitsInReg8Operand(from)) { |
| - Output(Bytecode::kMov, from.ToRawOperand(), to.ToRawOperand()); |
| - } else if (FitsInReg16Operand(to) && FitsInReg16Operand(from)) { |
| - Output(Bytecode::kMovWide, from.ToRawOperand(), to.ToRawOperand()); |
| + RegisterTranslationScope translator(this); |
|
rmcilroy
2016/01/22 17:50:56
Personally I would prefer that the RegisterTransla
|
| + if (FitsInReg8Operand(from) && FitsInReg8Operand(to)) { |
| + translator.set_bytecode(Bytecode::kMov); |
| + } else if (FitsInReg16Operand(from) && FitsInReg16Operand(to)) { |
| + translator.set_bytecode(Bytecode::kMovWide); |
| } else { |
| UNIMPLEMENTED(); |
| } |
| + from = translator.Translate(from); |
| + to = translator.Translate(to); |
| + Output(translator.bytecode(), from.ToRawOperand(), to.ToRawOperand()); |
| return *this; |
| } |
| +bool BytecodeArrayBuilder::MoveRegisterUntranslated(Register from, |
| + Register to) { |
| + if (!from.is_valid() || !to.is_valid()) { |
|
rmcilroy
2016/01/22 17:50:56
Just DCHECK(from.is_valid() && to.is_valid)) ?
|
| + UNIMPLEMENTED(); |
| + return false; |
| + } |
| + |
| + DCHECK(FitsInReg8OperandUntranslated(from) || |
| + FitsInReg8OperandUntranslated(to)); |
| + DCHECK(from != to); |
| + if (FitsInReg16OperandUntranslated(from) && |
| + FitsInReg16OperandUntranslated(to)) { |
| + Output(Bytecode::kMovWide, from.ToRawOperand(), to.ToRawOperand()); |
| + return true; |
| + } else { |
| + UNIMPLEMENTED(); |
| + return false; |
| + } |
| +} |
| + |
| + |
| BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal( |
| const Handle<String> name, int feedback_slot, LanguageMode language_mode, |
| TypeofMode typeof_mode) { |
| @@ -414,15 +492,17 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal( |
| BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context, |
| int slot_index) { |
| DCHECK(slot_index >= 0); |
| + RegisterTranslationScope translator(this); |
| if (FitsInIdx8Operand(slot_index)) { |
| - Output(Bytecode::kLdaContextSlot, context.ToRawOperand(), |
| - static_cast<uint8_t>(slot_index)); |
| + translator.set_bytecode(Bytecode::kLdaContextSlot); |
| } else if (FitsInIdx16Operand(slot_index)) { |
| - Output(Bytecode::kLdaContextSlotWide, context.ToRawOperand(), |
| - static_cast<uint16_t>(slot_index)); |
| + translator.set_bytecode(Bytecode::kLdaContextSlotWide); |
| } else { |
| UNIMPLEMENTED(); |
| } |
| + context = translator.Translate(context); |
| + Output(translator.bytecode(), context.ToRawOperand(), |
| + static_cast<uint16_t>(slot_index)); |
| return *this; |
| } |
| @@ -430,15 +510,17 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context, |
| BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context, |
| int slot_index) { |
| DCHECK(slot_index >= 0); |
| + RegisterTranslationScope translator(this); |
| if (FitsInIdx8Operand(slot_index)) { |
| - Output(Bytecode::kStaContextSlot, context.ToRawOperand(), |
| - static_cast<uint8_t>(slot_index)); |
| + translator.set_bytecode(Bytecode::kStaContextSlot); |
| } else if (FitsInIdx16Operand(slot_index)) { |
| - Output(Bytecode::kStaContextSlotWide, context.ToRawOperand(), |
| - static_cast<uint16_t>(slot_index)); |
| + translator.set_bytecode(Bytecode::kStaContextSlotWide); |
| } else { |
| UNIMPLEMENTED(); |
| } |
| + context = translator.Translate(context); |
| + Output(translator.bytecode(), context.ToRawOperand(), |
| + static_cast<uint16_t>(slot_index)); |
| return *this; |
| } |
| @@ -480,35 +562,39 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot( |
| BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( |
| Register object, const Handle<String> name, int feedback_slot, |
| LanguageMode language_mode) { |
| - Bytecode bytecode = BytecodeForLoadIC(language_mode); |
| + RegisterTranslationScope translator(this); |
| size_t name_index = GetConstantPoolEntry(name); |
| if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) { |
| - Output(bytecode, object.ToRawOperand(), static_cast<uint8_t>(name_index), |
| - static_cast<uint8_t>(feedback_slot)); |
| + translator.set_bytecode(BytecodeForLoadIC(language_mode)); |
| } else if (FitsInIdx16Operand(name_index) && |
| FitsInIdx16Operand(feedback_slot)) { |
| - Output(BytecodeForWideOperands(bytecode), object.ToRawOperand(), |
| - static_cast<uint16_t>(name_index), |
| - static_cast<uint16_t>(feedback_slot)); |
| + translator.set_bytecode( |
| + BytecodeForWideOperands(BytecodeForLoadIC(language_mode))); |
| } else { |
| UNIMPLEMENTED(); |
| } |
| + object = translator.Translate(object); |
| + Output(translator.bytecode(), object.ToRawOperand(), |
| + static_cast<uint16_t>(name_index), |
| + static_cast<uint16_t>(feedback_slot)); |
|
rmcilroy
2016/01/22 17:50:56
Maybe just cast directly to uint32_t now so that w
|
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( |
| Register object, int feedback_slot, LanguageMode language_mode) { |
| - Bytecode bytecode = BytecodeForKeyedLoadIC(language_mode); |
| + RegisterTranslationScope translator(this); |
| if (FitsInIdx8Operand(feedback_slot)) { |
| - Output(bytecode, object.ToRawOperand(), |
| - static_cast<uint8_t>(feedback_slot)); |
| + translator.set_bytecode(BytecodeForKeyedLoadIC(language_mode)); |
| } else if (FitsInIdx16Operand(feedback_slot)) { |
| - Output(BytecodeForWideOperands(bytecode), object.ToRawOperand(), |
| - static_cast<uint16_t>(feedback_slot)); |
| + translator.set_bytecode( |
| + BytecodeForWideOperands(BytecodeForKeyedLoadIC(language_mode))); |
| } else { |
| UNIMPLEMENTED(); |
| } |
| + object = translator.Translate(object); |
| + Output(translator.bytecode(), object.ToRawOperand(), |
| + static_cast<uint16_t>(feedback_slot)); |
| return *this; |
| } |
| @@ -516,19 +602,21 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( |
| BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( |
| Register object, const Handle<String> name, int feedback_slot, |
| LanguageMode language_mode) { |
| - Bytecode bytecode = BytecodeForStoreIC(language_mode); |
| size_t name_index = GetConstantPoolEntry(name); |
| + RegisterTranslationScope translator(this); |
| if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) { |
| - Output(bytecode, object.ToRawOperand(), static_cast<uint8_t>(name_index), |
| - static_cast<uint8_t>(feedback_slot)); |
| + translator.set_bytecode(BytecodeForStoreIC(language_mode)); |
| } else if (FitsInIdx16Operand(name_index) && |
| FitsInIdx16Operand(feedback_slot)) { |
| - Output(BytecodeForWideOperands(bytecode), object.ToRawOperand(), |
| - static_cast<uint16_t>(name_index), |
| - static_cast<uint16_t>(feedback_slot)); |
| + translator.set_bytecode( |
| + BytecodeForWideOperands(BytecodeForStoreIC(language_mode))); |
| } else { |
| UNIMPLEMENTED(); |
| } |
| + object = translator.Translate(object); |
| + Output(translator.bytecode(), object.ToRawOperand(), |
| + static_cast<uint16_t>(name_index), |
| + static_cast<uint16_t>(feedback_slot)); |
| return *this; |
| } |
| @@ -536,16 +624,19 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( |
| BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( |
| Register object, Register key, int feedback_slot, |
| LanguageMode language_mode) { |
| - Bytecode bytecode = BytecodeForKeyedStoreIC(language_mode); |
| + RegisterTranslationScope translator(this); |
| if (FitsInIdx8Operand(feedback_slot)) { |
| - Output(bytecode, object.ToRawOperand(), key.ToRawOperand(), |
| - static_cast<uint8_t>(feedback_slot)); |
| + translator.set_bytecode(BytecodeForKeyedStoreIC(language_mode)); |
| } else if (FitsInIdx16Operand(feedback_slot)) { |
| - Output(BytecodeForWideOperands(bytecode), object.ToRawOperand(), |
| - key.ToRawOperand(), static_cast<uint16_t>(feedback_slot)); |
| + translator.set_bytecode( |
| + BytecodeForWideOperands(BytecodeForKeyedStoreIC(language_mode))); |
| } else { |
| UNIMPLEMENTED(); |
| } |
| + object = translator.Translate(object); |
| + key = translator.Translate(key); |
| + Output(translator.bytecode(), object.ToRawOperand(), key.ToRawOperand(), |
| + static_cast<uint16_t>(feedback_slot)); |
| return *this; |
| } |
| @@ -640,13 +731,17 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral( |
| BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) { |
| - Output(Bytecode::kPushContext, context.ToRawOperand()); |
| + RegisterTranslationScope translator(this, Bytecode::kPushContext); |
| + context = translator.Translate(context); |
| + Output(translator.bytecode(), context.ToRawOperand()); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) { |
| - Output(Bytecode::kPopContext, context.ToRawOperand()); |
| + RegisterTranslationScope translator(this, Bytecode::kPopContext); |
| + context = translator.Translate(context); |
| + Output(translator.bytecode(), context.ToRawOperand()); |
| return *this; |
| } |
| @@ -969,20 +1064,26 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Return() { |
| BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare( |
| Register cache_info_triple) { |
| + RegisterTranslationScope translator(this); |
| if (FitsInReg8Operand(cache_info_triple)) { |
| - Output(Bytecode::kForInPrepare, cache_info_triple.ToRawOperand()); |
| + translator.set_bytecode(Bytecode::kForInPrepare); |
| } else if (FitsInReg16Operand(cache_info_triple)) { |
| - Output(Bytecode::kForInPrepareWide, cache_info_triple.ToRawOperand()); |
| + translator.set_bytecode(Bytecode::kForInPrepareWide); |
| } else { |
| UNIMPLEMENTED(); |
| } |
| + cache_info_triple = translator.Translate(cache_info_triple); |
| + Output(translator.bytecode(), cache_info_triple.ToRawOperand()); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::ForInDone(Register index, |
| Register cache_length) { |
| - Output(Bytecode::kForInDone, index.ToRawOperand(), |
| + RegisterTranslationScope translator(this, Bytecode::kForInDone); |
| + index = translator.Translate(index); |
| + cache_length = translator.Translate(cache_length); |
| + Output(translator.bytecode(), index.ToRawOperand(), |
| cache_length.ToRawOperand()); |
| return *this; |
| } |
| @@ -990,23 +1091,29 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::ForInDone(Register index, |
| BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext( |
| Register receiver, Register index, Register cache_type_array_pair) { |
| + RegisterTranslationScope translator(this); |
| if (FitsInReg8Operand(receiver) && FitsInReg8Operand(index) && |
| FitsInReg8Operand(cache_type_array_pair)) { |
| - Output(Bytecode::kForInNext, receiver.ToRawOperand(), index.ToRawOperand(), |
| - cache_type_array_pair.ToRawOperand()); |
| + translator.set_bytecode(Bytecode::kForInNext); |
| } else if (FitsInReg16Operand(receiver) && FitsInReg16Operand(index) && |
| FitsInReg16Operand(cache_type_array_pair)) { |
| - Output(Bytecode::kForInNextWide, receiver.ToRawOperand(), |
| - index.ToRawOperand(), cache_type_array_pair.ToRawOperand()); |
| + translator.set_bytecode(Bytecode::kForInNextWide); |
| } else { |
| UNIMPLEMENTED(); |
| } |
| + receiver = translator.Translate(receiver); |
| + index = translator.Translate(index); |
| + cache_type_array_pair = translator.Translate(cache_type_array_pair); |
| + Output(translator.bytecode(), receiver.ToRawOperand(), index.ToRawOperand(), |
| + cache_type_array_pair.ToRawOperand()); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) { |
| - Output(Bytecode::kForInStep, index.ToRawOperand()); |
| + RegisterTranslationScope translator(this, Bytecode::kForInStep); |
| + index = translator.Translate(index); |
| + Output(translator.bytecode(), index.ToRawOperand()); |
| return *this; |
| } |
| @@ -1051,20 +1158,22 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, |
| Register receiver, |
| size_t arg_count, |
| int feedback_slot) { |
| + RegisterTranslationScope translator(this); |
| if (FitsInReg8Operand(callable) && FitsInReg8Operand(receiver) && |
| FitsInIdx8Operand(arg_count) && FitsInIdx8Operand(feedback_slot)) { |
| - Output(Bytecode::kCall, callable.ToRawOperand(), receiver.ToRawOperand(), |
| - static_cast<uint8_t>(arg_count), |
| - static_cast<uint8_t>(feedback_slot)); |
| + translator.set_bytecode(Bytecode::kCall); |
| } else if (FitsInReg16Operand(callable) && FitsInReg16Operand(receiver) && |
| FitsInIdx16Operand(arg_count) && |
| FitsInIdx16Operand(feedback_slot)) { |
| - Output(Bytecode::kCallWide, callable.ToRawOperand(), |
| - receiver.ToRawOperand(), static_cast<uint16_t>(arg_count), |
| - static_cast<uint16_t>(feedback_slot)); |
| + translator.set_bytecode(Bytecode::kCallWide); |
| } else { |
| UNIMPLEMENTED(); |
| } |
| + callable = translator.Translate(callable); |
| + receiver = translator.Translate(receiver); |
| + Output(translator.bytecode(), callable.ToRawOperand(), |
| + receiver.ToRawOperand(), static_cast<uint16_t>(arg_count), |
| + static_cast<uint16_t>(feedback_slot)); |
| return *this; |
| } |
| @@ -1077,17 +1186,20 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, |
| first_arg = Register(0); |
| } |
| + RegisterTranslationScope translator(this); |
| if (FitsInReg8Operand(constructor) && FitsInReg8Operand(first_arg) && |
| FitsInIdx8Operand(arg_count)) { |
| - Output(Bytecode::kNew, constructor.ToRawOperand(), first_arg.ToRawOperand(), |
| - static_cast<uint8_t>(arg_count)); |
| + translator.set_bytecode(Bytecode::kNew); |
| } else if (FitsInReg16Operand(constructor) && FitsInReg16Operand(first_arg) && |
| FitsInIdx16Operand(arg_count)) { |
| - Output(Bytecode::kNewWide, constructor.ToRawOperand(), |
| - first_arg.ToRawOperand(), static_cast<uint16_t>(arg_count)); |
| + translator.set_bytecode(Bytecode::kNewWide); |
| } else { |
| UNIMPLEMENTED(); |
| } |
| + constructor = translator.Translate(constructor); |
| + first_arg = translator.Translate(first_arg); |
| + Output(translator.bytecode(), constructor.ToRawOperand(), |
| + first_arg.ToRawOperand(), static_cast<uint16_t>(arg_count)); |
| return *this; |
| } |
| @@ -1100,15 +1212,18 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( |
| DCHECK_EQ(0u, arg_count); |
| first_arg = Register(0); |
| } |
| + |
| + RegisterTranslationScope translator(this); |
| if (FitsInReg8Operand(first_arg) && FitsInIdx8Operand(arg_count)) { |
| - Output(Bytecode::kCallRuntime, static_cast<uint16_t>(function_id), |
| - first_arg.ToRawOperand(), static_cast<uint8_t>(arg_count)); |
| + translator.set_bytecode(Bytecode::kCallRuntime); |
| } else if (FitsInReg16Operand(first_arg) && FitsInIdx16Operand(arg_count)) { |
| - Output(Bytecode::kCallRuntimeWide, static_cast<uint16_t>(function_id), |
| - first_arg.ToRawOperand(), static_cast<uint16_t>(arg_count)); |
| + translator.set_bytecode(Bytecode::kCallRuntimeWide); |
| } else { |
| UNIMPLEMENTED(); |
| } |
| + first_arg = translator.Translate(first_arg); |
| + Output(translator.bytecode(), static_cast<uint16_t>(function_id), |
| + first_arg.ToRawOperand(), static_cast<uint16_t>(arg_count)); |
| return *this; |
| } |
| @@ -1122,19 +1237,22 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair( |
| DCHECK_EQ(0u, arg_count); |
| first_arg = Register(0); |
| } |
| + |
| + RegisterTranslationScope translator(this); |
| if (FitsInReg8Operand(first_arg) && FitsInIdx8Operand(arg_count) && |
| FitsInReg8Operand(first_return)) { |
| - Output(Bytecode::kCallRuntimeForPair, static_cast<uint16_t>(function_id), |
| - first_arg.ToRawOperand(), static_cast<uint8_t>(arg_count), |
| - first_return.ToRawOperand()); |
| + translator.set_bytecode(Bytecode::kCallRuntimeForPair); |
| } else if (FitsInReg16Operand(first_arg) && FitsInIdx16Operand(arg_count) && |
| FitsInReg16Operand(first_return)) { |
| - Output(Bytecode::kCallRuntimeForPairWide, |
| - static_cast<uint16_t>(function_id), first_arg.ToRawOperand(), |
| - static_cast<uint16_t>(arg_count), first_return.ToRawOperand()); |
| + translator.set_bytecode(Bytecode::kCallRuntimeForPairWide); |
| } else { |
| UNIMPLEMENTED(); |
| } |
| + first_arg = translator.Translate(first_arg); |
| + first_return = translator.Translate(first_return); |
| + Output(translator.bytecode(), static_cast<uint16_t>(function_id), |
| + first_arg.ToRawOperand(), static_cast<uint16_t>(arg_count), |
| + first_return.ToRawOperand()); |
| return *this; |
| } |
| @@ -1143,22 +1261,27 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index, |
| Register receiver, |
| size_t arg_count) { |
| DCHECK(FitsInIdx16Operand(context_index)); |
| + |
| + RegisterTranslationScope translator(this); |
| if (FitsInReg8Operand(receiver) && FitsInIdx8Operand(arg_count)) { |
| - Output(Bytecode::kCallJSRuntime, static_cast<uint16_t>(context_index), |
| - receiver.ToRawOperand(), static_cast<uint8_t>(arg_count)); |
| + translator.set_bytecode(Bytecode::kCallJSRuntime); |
| } else if (FitsInReg16Operand(receiver) && FitsInIdx16Operand(arg_count)) { |
| - Output(Bytecode::kCallJSRuntimeWide, static_cast<uint16_t>(context_index), |
| - receiver.ToRawOperand(), static_cast<uint16_t>(arg_count)); |
| + translator.set_bytecode(Bytecode::kCallJSRuntimeWide); |
| } else { |
| UNIMPLEMENTED(); |
| } |
| + receiver = translator.Translate(receiver); |
| + Output(translator.bytecode(), static_cast<uint16_t>(context_index), |
| + receiver.ToRawOperand(), static_cast<uint16_t>(arg_count)); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, |
| LanguageMode language_mode) { |
| - Output(BytecodeForDelete(language_mode), object.ToRawOperand()); |
| + RegisterTranslationScope translator(this, BytecodeForDelete(language_mode)); |
| + object = translator.Translate(object); |
| + Output(translator.bytecode(), object.ToRawOperand()); |
| return *this; |
| } |
| @@ -1174,9 +1297,14 @@ size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { |
| } |
| +void BytecodeArrayBuilder::ForgeTemporaryRegister() { |
| + temporary_register_count_++; |
| +} |
| + |
| + |
| int BytecodeArrayBuilder::BorrowTemporaryRegister() { |
| if (free_temporaries_.empty()) { |
| - temporary_register_count_ += 1; |
| + ForgeTemporaryRegister(); |
| return last_temporary_register().index(); |
| } else { |
| auto pos = free_temporaries_.begin(); |
| @@ -1195,7 +1323,7 @@ int BytecodeArrayBuilder::BorrowTemporaryRegisterNotInRange(int start_index, |
| // greater than end_index. |
| index = free_temporaries_.upper_bound(end_index); |
| if (index == free_temporaries_.end()) { |
| - temporary_register_count_ += 1; |
| + ForgeTemporaryRegister(); |
| return last_temporary_register().index(); |
| } |
| } else { |
| @@ -1227,11 +1355,29 @@ int BytecodeArrayBuilder::PrepareForConsecutiveTemporaryRegisters( |
| return -1; |
| } |
| + // TODO(oth): replace use of set<> here for free_temporaries with a |
| + // more efficient structure. And/or partition into two searches - |
| + // one before the translation window and one after. |
| + if (free_temporaries_.empty()) { |
|
rmcilroy
2016/01/22 17:50:56
Please add a comment on why you are having to forg
|
| + ForgeTemporaryRegister(); |
| + free_temporaries_.insert(last_temporary_register().index()); |
| + } |
| + |
| // Search within existing temporaries for a run. |
| auto start = free_temporaries_.begin(); |
| size_t run_length = 0; |
| for (auto run_end = start; run_end != free_temporaries_.end(); run_end++) { |
| - if (*run_end != *start + static_cast<int>(run_length)) { |
| + int expected = *start + static_cast<int>(run_length); |
| + if (*run_end != expected) { |
| + start = run_end; |
| + run_length = 0; |
| + } |
| + Register reg_start(*start); |
| + Register reg_expected(expected); |
| + if (RegisterTranslator::DistanceToTranslationWindow(reg_start) > 0 && |
| + RegisterTranslator::DistanceToTranslationWindow(reg_expected) <= 0) { |
| + // Run straddles the translation window boundary where there is |
| + // a hidden discontinuity. |
|
rmcilroy
2016/01/22 17:50:56
/s/discontinuity/hole in allocatable registers ?
|
| start = run_end; |
| run_length = 0; |
| } |
| @@ -1248,12 +1394,34 @@ int BytecodeArrayBuilder::PrepareForConsecutiveTemporaryRegisters( |
| run_length = 0; |
| } |
| + // Pad temporaries if extended run would cross translation boundary. |
| + Register reg_first(*start); |
| + Register reg_last(*start + static_cast<int>(count) - 1); |
| + DCHECK_GT(RegisterTranslator::DistanceToTranslationWindow(reg_first), |
| + RegisterTranslator::DistanceToTranslationWindow(reg_last)); |
| + while (RegisterTranslator::DistanceToTranslationWindow(reg_first) > 0 && |
| + RegisterTranslator::DistanceToTranslationWindow(reg_last) <= 0) { |
| + ForgeTemporaryRegister(); |
| + free_temporaries_.insert(last_temporary_register().index()); |
| + start = --free_temporaries_.end(); |
| + reg_first = Register(*start); |
| + reg_last = Register(*start + static_cast<int>(count) - 1); |
| + run_length = 0; |
| + } |
| + |
| // Ensure enough registers for run. |
| while (run_length++ < count) { |
| - temporary_register_count_++; |
| + ForgeTemporaryRegister(); |
| free_temporaries_.insert(last_temporary_register().index()); |
| } |
| - return last_temporary_register().index() - static_cast<int>(count) + 1; |
| + |
| + int run_start = |
| + last_temporary_register().index() - static_cast<int>(count) + 1; |
| + DCHECK(RegisterTranslator::DistanceToTranslationWindow(Register(run_start)) <= |
| + 0 || |
| + RegisterTranslator::DistanceToTranslationWindow( |
| + Register(run_start + static_cast<int>(count) - 1)) > 0); |
| + return run_start; |
| } |
| @@ -1324,10 +1492,14 @@ bool BytecodeArrayBuilder::RegisterIsValid(Register reg, |
| OperandType reg_type) const { |
| switch (Bytecodes::SizeOfOperand(reg_type)) { |
| case OperandSize::kByte: |
| - if (!FitsInReg8Operand(reg)) { return false; } |
| + if (!FitsInReg8OperandUntranslated(reg)) { |
| + return false; |
| + } |
| break; |
| case OperandSize::kShort: |
| - if (!FitsInReg16Operand(reg)) { return false; } |
| + if (!FitsInReg16OperandUntranslated(reg)) { |
| + return false; |
| + } |
| break; |
| case OperandSize::kNone: |
| UNREACHABLE(); |
| @@ -1340,10 +1512,15 @@ bool BytecodeArrayBuilder::RegisterIsValid(Register reg, |
| } else if (reg.is_parameter()) { |
| int parameter_index = reg.ToParameterIndex(parameter_count_); |
| return parameter_index >= 0 && parameter_index < parameter_count_; |
| - } else if (reg.index() < fixed_register_count()) { |
| - return true; |
| + } else if (translation_register_count() == 0) { |
| + if (reg.index() < fixed_register_count()) { |
| + return true; |
| + } else { |
| + return TemporaryRegisterIsLive(reg); |
| + } |
| } else { |
| - return TemporaryRegisterIsLive(reg); |
| + return reg.index() < (fixed_and_temporary_register_count() + |
| + translation_register_count()); |
|
rmcilroy
2016/01/22 17:50:56
Does this not check for the temp being live. Could
|
| } |
| } |
| @@ -1358,9 +1535,10 @@ bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) { |
| if (LastBytecodeInSameBlock()) { |
| PreviousBytecodeHelper previous_bytecode(*this); |
| Bytecode bytecode = previous_bytecode.GetBytecode(); |
| - if ((bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar) && |
| - (reg == Register::FromOperand(previous_bytecode.GetOperand(0)))) { |
| - return true; |
| + if (bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar) { |
| + Register previous = |
|
rmcilroy
2016/01/22 17:50:56
nit - previous_reg
|
| + Register::FromOperand(previous_bytecode.GetOperand(0)); |
| + return previous == reg; |
| } |
| } |
| return false; |
| @@ -1673,13 +1851,25 @@ bool BytecodeArrayBuilder::FitsInIdx16Operand(size_t value) { |
| // static |
| bool BytecodeArrayBuilder::FitsInReg8Operand(Register value) { |
| - return kMinInt8 <= value.index() && value.index() <= kMaxInt8; |
| + return RegisterTranslator::FitsInReg8Operand(value); |
| +} |
| + |
| + |
| +// static |
| +bool BytecodeArrayBuilder::FitsInReg8OperandUntranslated(Register value) { |
| + return value.is_byte_operand(); |
| } |
| // static |
| bool BytecodeArrayBuilder::FitsInReg16Operand(Register value) { |
| - return kMinInt16 <= value.index() && value.index() <= kMaxInt16; |
| + return RegisterTranslator::FitsInReg16Operand(value); |
| +} |
| + |
| + |
| +// static |
| +bool BytecodeArrayBuilder::FitsInReg16OperandUntranslated(Register value) { |
| + return value.is_short_operand(); |
| } |
| } // namespace interpreter |