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 |