Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(490)

Unified Diff: src/interpreter/bytecode-array-builder.cc

Issue 2393683004: [Interpreter] Optimize the Register Optimizer. (Closed)
Patch Set: Rebase Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/interpreter/bytecode-array-builder.h ('k') | src/interpreter/bytecode-operands.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/interpreter/bytecode-array-builder.cc
diff --git a/src/interpreter/bytecode-array-builder.cc b/src/interpreter/bytecode-array-builder.cc
index dfa395095abaf72da5407a415b7af5edb58b1410..7f22ccbb4b7eb00efcecdecc0b6e0f38c59bf9fc 100644
--- a/src/interpreter/bytecode-array-builder.cc
+++ b/src/interpreter/bytecode-array-builder.cc
@@ -31,7 +31,8 @@ BytecodeArrayBuilder::BytecodeArrayBuilder(
register_allocator_(fixed_register_count()),
bytecode_array_writer_(zone, &constant_array_builder_,
source_position_mode),
- pipeline_(&bytecode_array_writer_) {
+ pipeline_(&bytecode_array_writer_),
+ register_optimizer_(nullptr) {
DCHECK_GE(parameter_count_, 0);
DCHECK_GE(context_register_count_, 0);
DCHECK_GE(local_register_count_, 0);
@@ -45,7 +46,7 @@ BytecodeArrayBuilder::BytecodeArrayBuilder(
}
if (FLAG_ignition_reo) {
- pipeline_ = new (zone) BytecodeRegisterOptimizer(
+ register_optimizer_ = new (zone) BytecodeRegisterOptimizer(
zone, &register_allocator_, fixed_register_count(), parameter_count,
pipeline_);
}
@@ -75,108 +76,222 @@ Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) {
DCHECK(!bytecode_generated_);
bytecode_generated_ = true;
+ int register_count = total_register_count();
+
+ if (register_optimizer_) {
+ register_optimizer_->Flush();
+ register_count = register_optimizer_->maxiumum_register_index() + 1;
+ }
+
Handle<FixedArray> handler_table =
handler_table_builder()->ToHandlerTable(isolate);
- return pipeline_->ToBytecodeArray(isolate, total_register_count(),
- parameter_count(), handler_table);
-}
-
-void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
- uint32_t operand1, uint32_t operand2,
- uint32_t operand3) {
- DCHECK(OperandsAreValid(bytecode, 4, operand0, operand1, operand2, operand3));
- BytecodeNode node(bytecode, operand0, operand1, operand2, operand3,
- &latest_source_info_);
- pipeline()->Write(&node);
+ return pipeline_->ToBytecodeArray(isolate, register_count, parameter_count(),
+ handler_table);
+}
+
+BytecodeSourceInfo BytecodeArrayBuilder::CurrentSourcePosition(
+ Bytecode bytecode) {
+ BytecodeSourceInfo source_position;
+ if (latest_source_info_.is_valid()) {
+ // Statement positions need to be emitted immediately. Expression
+ // positions can be pushed back until a bytecode is found that can
+ // throw (if expression position filtering is turned on). We only
+ // invalidate the existing source position information if it is used.
+ if (latest_source_info_.is_statement() ||
+ !FLAG_ignition_filter_expression_positions ||
+ !Bytecodes::IsWithoutExternalSideEffects(bytecode)) {
+ source_position = latest_source_info_;
+ latest_source_info_.set_invalid();
+ }
+ }
+ return source_position;
}
-void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
- uint32_t operand1, uint32_t operand2) {
- DCHECK(OperandsAreValid(bytecode, 3, operand0, operand1, operand2));
- BytecodeNode node(bytecode, operand0, operand1, operand2,
- &latest_source_info_);
- pipeline()->Write(&node);
-}
+namespace {
-void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
- uint32_t operand1) {
- DCHECK(OperandsAreValid(bytecode, 2, operand0, operand1));
- BytecodeNode node(bytecode, operand0, operand1, &latest_source_info_);
- pipeline()->Write(&node);
-}
+template <OperandTypeInfo type_info>
+class UnsignedOperandHelper {
+ public:
+ INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, size_t value)) {
+ DCHECK(IsValid(value));
+ return static_cast<uint32_t>(value);
+ }
-void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0) {
- DCHECK(OperandsAreValid(bytecode, 1, operand0));
- BytecodeNode node(bytecode, operand0, &latest_source_info_);
- pipeline()->Write(&node);
-}
+ INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, int value)) {
+ DCHECK_GE(value, 0);
+ return Convert(builder, static_cast<size_t>(value));
+ }
-void BytecodeArrayBuilder::Output(Bytecode bytecode) {
- DCHECK(OperandsAreValid(bytecode, 0));
- BytecodeNode node(bytecode, &latest_source_info_);
- pipeline()->Write(&node);
-}
+ private:
+ static bool IsValid(size_t value) {
+ switch (type_info) {
+ case OperandTypeInfo::kFixedUnsignedByte:
+ return value <= kMaxUInt8;
+ case OperandTypeInfo::kFixedUnsignedShort:
+ return value <= kMaxUInt16;
+ case OperandTypeInfo::kScalableUnsignedByte:
+ return value <= kMaxUInt32;
+ default:
+ UNREACHABLE();
+ return false;
+ }
+ }
+};
+
+template <OperandType>
+class OperandHelper {};
+
+#define DEFINE_UNSIGNED_OPERAND_HELPER(Name, Type) \
+ template <> \
+ class OperandHelper<OperandType::k##Name> \
+ : public UnsignedOperandHelper<Type> {};
+UNSIGNED_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
+#undef DEFINE_UNSIGNED_OPERAND_HELPER
+
+template <>
+class OperandHelper<OperandType::kImm> {
+ public:
+ INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, int value)) {
+ return static_cast<uint32_t>(value);
+ }
+};
-void BytecodeArrayBuilder::OutputJump(Bytecode bytecode, BytecodeLabel* label) {
- BytecodeNode node(bytecode, 0, &latest_source_info_);
- pipeline_->WriteJump(&node, label);
- LeaveBasicBlock();
-}
+template <>
+class OperandHelper<OperandType::kReg> {
+ public:
+ INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, Register reg)) {
+ return builder->GetInputRegisterOperand(reg);
+ }
+};
+
+template <>
+class OperandHelper<OperandType::kRegList> {
+ public:
+ INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder,
+ RegisterList reg_list)) {
+ return builder->GetInputRegisterListOperand(reg_list);
+ }
+};
+
+template <>
+class OperandHelper<OperandType::kRegPair> {
+ public:
+ INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder,
+ RegisterList reg_list)) {
+ DCHECK_EQ(reg_list.register_count(), 2);
+ return builder->GetInputRegisterListOperand(reg_list);
+ }
+};
-void BytecodeArrayBuilder::OutputJump(Bytecode bytecode, uint32_t operand0,
- BytecodeLabel* label) {
- BytecodeNode node(bytecode, 0, operand0, &latest_source_info_);
- pipeline_->WriteJump(&node, label);
- LeaveBasicBlock();
-}
+template <>
+class OperandHelper<OperandType::kRegOut> {
+ public:
+ INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, Register reg)) {
+ return builder->GetOutputRegisterOperand(reg);
+ }
+};
+
+template <>
+class OperandHelper<OperandType::kRegOutPair> {
+ public:
+ INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder,
+ RegisterList reg_list)) {
+ DCHECK_EQ(2, reg_list.register_count());
+ return builder->GetOutputRegisterListOperand(reg_list);
+ }
+};
+
+template <>
+class OperandHelper<OperandType::kRegOutTriple> {
+ public:
+ INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder,
+ RegisterList reg_list)) {
+ DCHECK_EQ(3, reg_list.register_count());
+ return builder->GetOutputRegisterListOperand(reg_list);
+ }
+};
+
+} // namespace
+
+template <OperandType... operand_types>
+class BytecodeNodeBuilder {
+ public:
+ template <typename... Operands>
+ INLINE(static BytecodeNode Make(BytecodeArrayBuilder* builder,
+ BytecodeSourceInfo source_info,
+ Bytecode bytecode, Operands... operands)) {
+ builder->PrepareToOutputBytecode(bytecode);
+ // The "OperandHelper<operand_types>::Convert(builder, operands)..." will
+ // expand both the OperandType... and Operands... parameter packs e.g. for:
+ // BytecodeNodeBuilder<OperandType::kReg, OperandType::kImm>::Make<
+ // Register, int>(..., Register reg, int immediate)
+ // the code will expand into:
+ // OperandHelper<OperandType::kReg>::Convert(builder, reg),
+ // OperandHelper<OperandType::kImm>::Convert(builder, immediate),
+ return BytecodeNode(
+ bytecode, OperandHelper<operand_types>::Convert(builder, operands)...,
+ source_info);
+ }
+};
+
+#define DEFINE_BYTECODE_OUTPUT(name, accumulator_use, ...) \
+ template <typename... Operands> \
+ void BytecodeArrayBuilder::Output##name(Operands... operands) { \
+ BytecodeNode node(BytecodeNodeBuilder<__VA_ARGS__>::Make<Operands...>( \
+ this, CurrentSourcePosition(Bytecode::k##name), Bytecode::k##name, \
+ operands...)); \
+ pipeline()->Write(&node); \
+ } \
+ \
+ template <typename... Operands> \
+ void BytecodeArrayBuilder::Output##name(BytecodeLabel* label, \
+ Operands... operands) { \
+ DCHECK(Bytecodes::IsJump(Bytecode::k##name)); \
+ BytecodeNode node(BytecodeNodeBuilder<__VA_ARGS__>::Make<Operands...>( \
+ this, CurrentSourcePosition(Bytecode::k##name), Bytecode::k##name, \
+ operands...)); \
+ pipeline()->WriteJump(&node, label); \
+ LeaveBasicBlock(); \
+ }
+BYTECODE_LIST(DEFINE_BYTECODE_OUTPUT)
+#undef DEFINE_BYTECODE_OUTPUT
BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
Register reg,
int feedback_slot) {
switch (op) {
case Token::Value::ADD:
- Output(Bytecode::kAdd, RegisterOperand(reg),
- UnsignedOperand(feedback_slot));
+ OutputAdd(reg, feedback_slot);
break;
case Token::Value::SUB:
- Output(Bytecode::kSub, RegisterOperand(reg),
- UnsignedOperand(feedback_slot));
+ OutputSub(reg, feedback_slot);
break;
case Token::Value::MUL:
- Output(Bytecode::kMul, RegisterOperand(reg),
- UnsignedOperand(feedback_slot));
+ OutputMul(reg, feedback_slot);
break;
case Token::Value::DIV:
- Output(Bytecode::kDiv, RegisterOperand(reg),
- UnsignedOperand(feedback_slot));
+ OutputDiv(reg, feedback_slot);
break;
case Token::Value::MOD:
- Output(Bytecode::kMod, RegisterOperand(reg),
- UnsignedOperand(feedback_slot));
+ OutputMod(reg, feedback_slot);
break;
case Token::Value::BIT_OR:
- Output(Bytecode::kBitwiseOr, RegisterOperand(reg),
- UnsignedOperand(feedback_slot));
+ OutputBitwiseOr(reg, feedback_slot);
break;
case Token::Value::BIT_XOR:
- Output(Bytecode::kBitwiseXor, RegisterOperand(reg),
- UnsignedOperand(feedback_slot));
+ OutputBitwiseXor(reg, feedback_slot);
break;
case Token::Value::BIT_AND:
- Output(Bytecode::kBitwiseAnd, RegisterOperand(reg),
- UnsignedOperand(feedback_slot));
+ OutputBitwiseAnd(reg, feedback_slot);
break;
case Token::Value::SHL:
- Output(Bytecode::kShiftLeft, RegisterOperand(reg),
- UnsignedOperand(feedback_slot));
+ OutputShiftLeft(reg, feedback_slot);
break;
case Token::Value::SAR:
- Output(Bytecode::kShiftRight, RegisterOperand(reg),
- UnsignedOperand(feedback_slot));
+ OutputShiftRight(reg, feedback_slot);
break;
case Token::Value::SHR:
- Output(Bytecode::kShiftRightLogical, RegisterOperand(reg),
- UnsignedOperand(feedback_slot));
+ OutputShiftRightLogical(reg, feedback_slot);
break;
default:
UNREACHABLE();
@@ -187,21 +302,21 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op,
int feedback_slot) {
if (op == Token::Value::ADD) {
- Output(Bytecode::kInc, UnsignedOperand(feedback_slot));
+ OutputInc(feedback_slot);
} else {
DCHECK_EQ(op, Token::Value::SUB);
- Output(Bytecode::kDec, UnsignedOperand(feedback_slot));
+ OutputDec(feedback_slot);
}
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() {
- Output(Bytecode::kToBooleanLogicalNot);
+ OutputToBooleanLogicalNot();
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() {
- Output(Bytecode::kTypeOf);
+ OutputTypeOf();
return *this;
}
@@ -209,38 +324,31 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
Token::Value op, Register reg, int feedback_slot) {
switch (op) {
case Token::Value::EQ:
- Output(Bytecode::kTestEqual, RegisterOperand(reg),
- UnsignedOperand(feedback_slot));
+ OutputTestEqual(reg, feedback_slot);
break;
case Token::Value::NE:
- Output(Bytecode::kTestNotEqual, RegisterOperand(reg),
- UnsignedOperand(feedback_slot));
+ OutputTestNotEqual(reg, feedback_slot);
break;
case Token::Value::EQ_STRICT:
- Output(Bytecode::kTestEqualStrict, RegisterOperand(reg),
- UnsignedOperand(feedback_slot));
+ OutputTestEqualStrict(reg, feedback_slot);
break;
case Token::Value::LT:
- Output(Bytecode::kTestLessThan, RegisterOperand(reg),
- UnsignedOperand(feedback_slot));
+ OutputTestLessThan(reg, feedback_slot);
break;
case Token::Value::GT:
- Output(Bytecode::kTestGreaterThan, RegisterOperand(reg),
- UnsignedOperand(feedback_slot));
+ OutputTestGreaterThan(reg, feedback_slot);
break;
case Token::Value::LTE:
- Output(Bytecode::kTestLessThanOrEqual, RegisterOperand(reg),
- UnsignedOperand(feedback_slot));
+ OutputTestLessThanOrEqual(reg, feedback_slot);
break;
case Token::Value::GTE:
- Output(Bytecode::kTestGreaterThanOrEqual, RegisterOperand(reg),
- UnsignedOperand(feedback_slot));
+ OutputTestGreaterThanOrEqual(reg, feedback_slot);
break;
case Token::Value::INSTANCEOF:
- Output(Bytecode::kTestInstanceOf, RegisterOperand(reg));
+ OutputTestInstanceOf(reg);
break;
case Token::Value::IN:
- Output(Bytecode::kTestIn, RegisterOperand(reg));
+ OutputTestIn(reg);
break;
default:
UNREACHABLE();
@@ -250,7 +358,7 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry(
size_t entry) {
- Output(Bytecode::kLdaConstant, UnsignedOperand(entry));
+ OutputLdaConstant(entry);
return *this;
}
@@ -258,70 +366,82 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
v8::internal::Smi* smi) {
int32_t raw_smi = smi->value();
if (raw_smi == 0) {
- Output(Bytecode::kLdaZero);
+ OutputLdaZero();
} else {
- Output(Bytecode::kLdaSmi, SignedOperand(raw_smi));
+ OutputLdaSmi(raw_smi);
}
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) {
size_t entry = GetConstantPoolEntry(object);
- Output(Bytecode::kLdaConstant, UnsignedOperand(entry));
+ OutputLdaConstant(entry);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() {
- Output(Bytecode::kLdaUndefined);
+ OutputLdaUndefined();
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() {
- Output(Bytecode::kLdaNull);
+ OutputLdaNull();
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() {
- Output(Bytecode::kLdaTheHole);
+ OutputLdaTheHole();
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() {
- Output(Bytecode::kLdaTrue);
+ OutputLdaTrue();
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() {
- Output(Bytecode::kLdaFalse);
+ OutputLdaFalse();
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister(
Register reg) {
- Output(Bytecode::kLdar, RegisterOperand(reg));
+ if (register_optimizer_) {
+ register_optimizer_->DoLdar(reg, CurrentSourcePosition(Bytecode::kLdar));
+ } else {
+ OutputLdar(reg);
+ }
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister(
Register reg) {
- Output(Bytecode::kStar, RegisterOperand(reg));
+ if (register_optimizer_) {
+ register_optimizer_->DoStar(reg, CurrentSourcePosition(Bytecode::kStar));
+ } else {
+ OutputStar(reg);
+ }
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from,
Register to) {
DCHECK(from != to);
- Output(Bytecode::kMov, RegisterOperand(from), RegisterOperand(to));
+ if (register_optimizer_) {
+ register_optimizer_->DoMov(from, to, CurrentSourcePosition(Bytecode::kMov));
+ } else {
+ OutputMov(from, to);
+ }
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(int feedback_slot,
TypeofMode typeof_mode) {
if (typeof_mode == INSIDE_TYPEOF) {
- Output(Bytecode::kLdaGlobalInsideTypeof, feedback_slot);
+ OutputLdaGlobalInsideTypeof(feedback_slot);
} else {
DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF);
- Output(Bytecode::kLdaGlobal, UnsignedOperand(feedback_slot));
+ OutputLdaGlobal(feedback_slot);
}
return *this;
}
@@ -330,12 +450,10 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal(
const Handle<String> name, int feedback_slot, LanguageMode language_mode) {
size_t name_index = GetConstantPoolEntry(name);
if (language_mode == SLOPPY) {
- Output(Bytecode::kStaGlobalSloppy, UnsignedOperand(name_index),
- UnsignedOperand(feedback_slot));
+ OutputStaGlobalSloppy(name_index, feedback_slot);
} else {
DCHECK_EQ(language_mode, STRICT);
- Output(Bytecode::kStaGlobalStrict, UnsignedOperand(name_index),
- UnsignedOperand(feedback_slot));
+ OutputStaGlobalStrict(name_index, feedback_slot);
}
return *this;
}
@@ -343,16 +461,14 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal(
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context,
int slot_index,
int depth) {
- Output(Bytecode::kLdaContextSlot, RegisterOperand(context),
- UnsignedOperand(slot_index), UnsignedOperand(depth));
+ OutputLdaContextSlot(context, slot_index, depth);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context,
int slot_index,
int depth) {
- Output(Bytecode::kStaContextSlot, RegisterOperand(context),
- UnsignedOperand(slot_index), UnsignedOperand(depth));
+ OutputStaContextSlot(context, slot_index, depth);
return *this;
}
@@ -360,10 +476,10 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot(
const Handle<String> name, TypeofMode typeof_mode) {
size_t name_index = GetConstantPoolEntry(name);
if (typeof_mode == INSIDE_TYPEOF) {
- Output(Bytecode::kLdaLookupSlotInsideTypeof, UnsignedOperand(name_index));
+ OutputLdaLookupSlotInsideTypeof(name_index);
} else {
DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF);
- Output(Bytecode::kLdaLookupSlot, UnsignedOperand(name_index));
+ OutputLdaLookupSlot(name_index);
}
return *this;
}
@@ -371,24 +487,26 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot(
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupContextSlot(
const Handle<String> name, TypeofMode typeof_mode, int slot_index,
int depth) {
- Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF)
- ? Bytecode::kLdaLookupContextSlotInsideTypeof
- : Bytecode::kLdaLookupContextSlot;
size_t name_index = GetConstantPoolEntry(name);
- Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(slot_index),
- UnsignedOperand(depth));
+ if (typeof_mode == INSIDE_TYPEOF) {
+ OutputLdaLookupContextSlotInsideTypeof(name_index, slot_index, depth);
+ } else {
+ DCHECK(typeof_mode == NOT_INSIDE_TYPEOF);
+ OutputLdaLookupContextSlot(name_index, slot_index, depth);
+ }
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupGlobalSlot(
const Handle<String> name, TypeofMode typeof_mode, int feedback_slot,
int depth) {
- Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF)
- ? Bytecode::kLdaLookupGlobalSlotInsideTypeof
- : Bytecode::kLdaLookupGlobalSlot;
size_t name_index = GetConstantPoolEntry(name);
- Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(feedback_slot),
- UnsignedOperand(depth));
+ if (typeof_mode == INSIDE_TYPEOF) {
+ OutputLdaLookupGlobalSlotInsideTypeof(name_index, feedback_slot, depth);
+ } else {
+ DCHECK(typeof_mode == NOT_INSIDE_TYPEOF);
+ OutputLdaLookupGlobalSlot(name_index, feedback_slot, depth);
+ }
return *this;
}
@@ -396,10 +514,10 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot(
const Handle<String> name, LanguageMode language_mode) {
size_t name_index = GetConstantPoolEntry(name);
if (language_mode == SLOPPY) {
- Output(Bytecode::kStaLookupSlotSloppy, UnsignedOperand(name_index));
+ OutputStaLookupSlotSloppy(name_index);
} else {
DCHECK_EQ(language_mode, STRICT);
- Output(Bytecode::kStaLookupSlotStrict, UnsignedOperand(name_index));
+ OutputStaLookupSlotStrict(name_index);
}
return *this;
}
@@ -407,15 +525,13 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot(
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
Register object, const Handle<Name> name, int feedback_slot) {
size_t name_index = GetConstantPoolEntry(name);
- Output(Bytecode::kLdaNamedProperty, RegisterOperand(object),
- UnsignedOperand(name_index), UnsignedOperand(feedback_slot));
+ OutputLdaNamedProperty(object, name_index, feedback_slot);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
Register object, int feedback_slot) {
- Output(Bytecode::kLdaKeyedProperty, RegisterOperand(object),
- UnsignedOperand(feedback_slot));
+ OutputLdaKeyedProperty(object, feedback_slot);
return *this;
}
@@ -424,12 +540,10 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
LanguageMode language_mode) {
size_t name_index = GetConstantPoolEntry(name);
if (language_mode == SLOPPY) {
- Output(Bytecode::kStaNamedPropertySloppy, RegisterOperand(object),
- UnsignedOperand(name_index), UnsignedOperand(feedback_slot));
+ OutputStaNamedPropertySloppy(object, name_index, feedback_slot);
} else {
DCHECK_EQ(language_mode, STRICT);
- Output(Bytecode::kStaNamedPropertyStrict, RegisterOperand(object),
- UnsignedOperand(name_index), UnsignedOperand(feedback_slot));
+ OutputStaNamedPropertyStrict(object, name_index, feedback_slot);
}
return *this;
}
@@ -438,27 +552,24 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty(
Register object, Register key, int feedback_slot,
LanguageMode language_mode) {
if (language_mode == SLOPPY) {
- Output(Bytecode::kStaKeyedPropertySloppy, RegisterOperand(object),
- RegisterOperand(key), UnsignedOperand(feedback_slot));
+ OutputStaKeyedPropertySloppy(object, key, feedback_slot);
} else {
DCHECK_EQ(language_mode, STRICT);
- Output(Bytecode::kStaKeyedPropertyStrict, RegisterOperand(object),
- RegisterOperand(key), UnsignedOperand(feedback_slot));
+ OutputStaKeyedPropertyStrict(object, key, feedback_slot);
}
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(size_t entry,
int flags) {
- Output(Bytecode::kCreateClosure, UnsignedOperand(entry),
- UnsignedOperand(flags));
+ OutputCreateClosure(entry, flags);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateBlockContext(
Handle<ScopeInfo> scope_info) {
size_t entry = GetConstantPoolEntry(scope_info);
- Output(Bytecode::kCreateBlockContext, UnsignedOperand(entry));
+ OutputCreateBlockContext(entry);
return *this;
}
@@ -466,21 +577,19 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CreateCatchContext(
Register exception, Handle<String> name, Handle<ScopeInfo> scope_info) {
size_t name_index = GetConstantPoolEntry(name);
size_t scope_info_index = GetConstantPoolEntry(scope_info);
- Output(Bytecode::kCreateCatchContext, RegisterOperand(exception),
- UnsignedOperand(name_index), UnsignedOperand(scope_info_index));
+ OutputCreateCatchContext(exception, name_index, scope_info_index);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateFunctionContext(int slots) {
- Output(Bytecode::kCreateFunctionContext, UnsignedOperand(slots));
+ OutputCreateFunctionContext(slots);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext(
Register object, Handle<ScopeInfo> scope_info) {
size_t scope_info_index = GetConstantPoolEntry(scope_info);
- Output(Bytecode::kCreateWithContext, RegisterOperand(object),
- UnsignedOperand(scope_info_index));
+ OutputCreateWithContext(object, scope_info_index);
return *this;
}
@@ -488,13 +597,13 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments(
CreateArgumentsType type) {
switch (type) {
case CreateArgumentsType::kMappedArguments:
- Output(Bytecode::kCreateMappedArguments);
+ OutputCreateMappedArguments();
break;
case CreateArgumentsType::kUnmappedArguments:
- Output(Bytecode::kCreateUnmappedArguments);
+ OutputCreateUnmappedArguments();
break;
case CreateArgumentsType::kRestParameter:
- Output(Bytecode::kCreateRestParameter);
+ OutputCreateRestParameter();
break;
default:
UNREACHABLE();
@@ -505,17 +614,14 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments(
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral(
Handle<String> pattern, int literal_index, int flags) {
size_t pattern_entry = GetConstantPoolEntry(pattern);
- Output(Bytecode::kCreateRegExpLiteral, UnsignedOperand(pattern_entry),
- UnsignedOperand(literal_index), UnsignedOperand(flags));
+ OutputCreateRegExpLiteral(pattern_entry, literal_index, flags);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
Handle<FixedArray> constant_elements, int literal_index, int flags) {
size_t constant_elements_entry = GetConstantPoolEntry(constant_elements);
- Output(Bytecode::kCreateArrayLiteral,
- UnsignedOperand(constant_elements_entry),
- UnsignedOperand(literal_index), UnsignedOperand(flags));
+ OutputCreateArrayLiteral(constant_elements_entry, literal_index, flags);
return *this;
}
@@ -523,42 +629,43 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral(
Handle<FixedArray> constant_properties, int literal_index, int flags,
Register output) {
size_t constant_properties_entry = GetConstantPoolEntry(constant_properties);
- Output(Bytecode::kCreateObjectLiteral,
- UnsignedOperand(constant_properties_entry),
- UnsignedOperand(literal_index), UnsignedOperand(flags),
- RegisterOperand(output));
+ OutputCreateObjectLiteral(constant_properties_entry, literal_index, flags,
+ output);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) {
- Output(Bytecode::kPushContext, RegisterOperand(context));
+ OutputPushContext(context);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) {
- Output(Bytecode::kPopContext, RegisterOperand(context));
+ OutputPopContext(context);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToObject(
Register out) {
- Output(Bytecode::kToObject, RegisterOperand(out));
+ OutputToObject(out);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToName(
Register out) {
- Output(Bytecode::kToName, RegisterOperand(out));
+ OutputToName(out);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToNumber(
Register out) {
- Output(Bytecode::kToNumber, RegisterOperand(out));
+ OutputToNumber(out);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) {
+ // Flush the register optimizer when binding a label to ensure all
+ // expected registers are valid when jumping to this label.
+ if (register_optimizer_) register_optimizer_->Flush();
pipeline_->BindLabel(label);
LeaveBasicBlock();
return *this;
@@ -572,42 +679,42 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target,
}
BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
- OutputJump(Bytecode::kJump, label);
+ OutputJump(label, 0);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) {
// The peephole optimizer attempts to simplify JumpIfToBooleanTrue
// to JumpIfTrue.
- OutputJump(Bytecode::kJumpIfToBooleanTrue, label);
+ OutputJumpIfToBooleanTrue(label, 0);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) {
- OutputJump(Bytecode::kJumpIfToBooleanFalse, label);
+ OutputJumpIfToBooleanFalse(label, 0);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) {
- OutputJump(Bytecode::kJumpIfNull, label);
+ OutputJumpIfNull(label, 0);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
BytecodeLabel* label) {
- OutputJump(Bytecode::kJumpIfUndefined, label);
+ OutputJumpIfUndefined(label, 0);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole(
BytecodeLabel* label) {
- OutputJump(Bytecode::kJumpIfNotHole, label);
+ OutputJumpIfNotHole(label, 0);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label,
int loop_depth) {
- OutputJump(Bytecode::kJumpLoop, UnsignedOperand(loop_depth), label);
+ OutputJumpLoop(label, 0, loop_depth);
return *this;
}
@@ -625,44 +732,42 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) {
// statement's position.
latest_source_info_.ForceExpressionPosition(position);
}
- Output(Bytecode::kStackCheck);
+ OutputStackCheck();
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() {
- Output(Bytecode::kThrow);
+ OutputThrow();
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() {
- Output(Bytecode::kReThrow);
+ OutputReThrow();
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
SetReturnPosition();
- Output(Bytecode::kReturn);
+ OutputReturn();
return_seen_in_block_ = true;
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() {
- Output(Bytecode::kDebugger);
+ OutputDebugger();
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare(
Register receiver, RegisterList cache_info_triple) {
DCHECK_EQ(3, cache_info_triple.register_count());
- Output(Bytecode::kForInPrepare, RegisterOperand(receiver),
- RegisterOperand(cache_info_triple.first_register()));
+ OutputForInPrepare(receiver, cache_info_triple);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::ForInContinue(
Register index, Register cache_length) {
- Output(Bytecode::kForInContinue, RegisterOperand(index),
- RegisterOperand(cache_length));
+ OutputForInContinue(index, cache_length);
return *this;
}
@@ -670,27 +775,24 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext(
Register receiver, Register index, RegisterList cache_type_array_pair,
int feedback_slot) {
DCHECK_EQ(2, cache_type_array_pair.register_count());
- Output(Bytecode::kForInNext, RegisterOperand(receiver),
- RegisterOperand(index),
- RegisterOperand(cache_type_array_pair.first_register()),
- UnsignedOperand(feedback_slot));
+ OutputForInNext(receiver, index, cache_type_array_pair, feedback_slot);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) {
- Output(Bytecode::kForInStep, RegisterOperand(index));
+ OutputForInStep(index);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator(
Register generator) {
- Output(Bytecode::kSuspendGenerator, RegisterOperand(generator));
+ OutputSuspendGenerator(generator);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator(
Register generator) {
- Output(Bytecode::kResumeGenerator, RegisterOperand(generator));
+ OutputResumeGenerator(generator);
return *this;
}
@@ -724,16 +826,10 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable,
int feedback_slot,
TailCallMode tail_call_mode) {
if (tail_call_mode == TailCallMode::kDisallow) {
- Output(Bytecode::kCall, RegisterOperand(callable),
- RegisterOperand(args.first_register()),
- UnsignedOperand(args.register_count()),
- UnsignedOperand(feedback_slot));
+ OutputCall(callable, args, args.register_count(), feedback_slot);
} else {
DCHECK(tail_call_mode == TailCallMode::kAllow);
- Output(Bytecode::kTailCall, RegisterOperand(callable),
- RegisterOperand(args.first_register()),
- UnsignedOperand(args.register_count()),
- UnsignedOperand(feedback_slot));
+ OutputTailCall(callable, args, args.register_count(), feedback_slot);
}
return *this;
}
@@ -741,10 +837,7 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable,
BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor,
RegisterList args,
int feedback_slot_id) {
- Output(Bytecode::kNew, RegisterOperand(constructor),
- RegisterOperand(args.first_register()),
- UnsignedOperand(args.register_count()),
- UnsignedOperand(feedback_slot_id));
+ OutputNew(constructor, args, args.register_count(), feedback_slot_id);
return *this;
}
@@ -752,17 +845,15 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
Runtime::FunctionId function_id, RegisterList args) {
DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size);
DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort);
- Bytecode bytecode;
- uint32_t id;
if (IntrinsicsHelper::IsSupported(function_id)) {
- bytecode = Bytecode::kInvokeIntrinsic;
- id = static_cast<uint32_t>(IntrinsicsHelper::FromRuntimeId(function_id));
+ IntrinsicsHelper::IntrinsicId intrinsic_id =
+ IntrinsicsHelper::FromRuntimeId(function_id);
+ OutputInvokeIntrinsic(static_cast<int>(intrinsic_id), args,
+ args.register_count());
} else {
- bytecode = Bytecode::kCallRuntime;
- id = static_cast<uint32_t>(function_id);
+ OutputCallRuntime(static_cast<int>(function_id), args,
+ args.register_count());
}
- Output(bytecode, id, RegisterOperand(args.first_register()),
- UnsignedOperand(args.register_count()));
return *this;
}
@@ -782,10 +873,8 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size);
DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort);
DCHECK_EQ(2, return_pair.register_count());
- Output(Bytecode::kCallRuntimeForPair, static_cast<uint16_t>(function_id),
- RegisterOperand(args.first_register()),
- UnsignedOperand(args.register_count()),
- RegisterOperand(return_pair.first_register()));
+ OutputCallRuntimeForPair(static_cast<uint16_t>(function_id), args,
+ args.register_count(), return_pair);
return *this;
}
@@ -797,19 +886,17 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index,
RegisterList args) {
- Output(Bytecode::kCallJSRuntime, UnsignedOperand(context_index),
- RegisterOperand(args.first_register()),
- UnsignedOperand(args.register_count()));
+ OutputCallJSRuntime(context_index, args, args.register_count());
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object,
LanguageMode language_mode) {
if (language_mode == SLOPPY) {
- Output(Bytecode::kDeletePropertySloppy, RegisterOperand(object));
+ OutputDeletePropertySloppy(object);
} else {
DCHECK_EQ(language_mode, STRICT);
- Output(Bytecode::kDeletePropertyStrict, RegisterOperand(object));
+ OutputDeletePropertyStrict(object);
}
return *this;
}
@@ -850,88 +937,50 @@ bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const {
}
}
-bool BytecodeArrayBuilder::OperandsAreValid(
- Bytecode bytecode, int operand_count, uint32_t operand0, uint32_t operand1,
- uint32_t operand2, uint32_t operand3) const {
- if (Bytecodes::NumberOfOperands(bytecode) != operand_count) {
- return false;
- }
-
- uint32_t operands[] = {operand0, operand1, operand2, operand3};
- const OperandType* operand_types = Bytecodes::GetOperandTypes(bytecode);
- for (int i = 0; i < operand_count; ++i) {
- switch (operand_types[i]) {
- case OperandType::kNone:
+bool BytecodeArrayBuilder::RegisterListIsValid(RegisterList reg_list) const {
+ if (reg_list.register_count() == 0) {
+ return reg_list.first_register() == Register(0);
+ } else {
+ int first_reg_index = reg_list.first_register().index();
+ for (int i = 0; i < reg_list.register_count(); i++) {
+ if (!RegisterIsValid(Register(first_reg_index + i))) {
return false;
- case OperandType::kFlag8:
- case OperandType::kIntrinsicId:
- if (Bytecodes::SizeForUnsignedOperand(operands[i]) >
- OperandSize::kByte) {
- return false;
- }
- break;
- case OperandType::kRuntimeId:
- if (Bytecodes::SizeForUnsignedOperand(operands[i]) >
- OperandSize::kShort) {
- return false;
- }
- break;
- case OperandType::kIdx:
- // TODO(leszeks): Possibly split this up into constant pool indices and
- // other indices, for checking.
- break;
- case OperandType::kUImm:
- case OperandType::kImm:
- break;
- case OperandType::kRegList: {
- CHECK_LT(i, operand_count - 1);
- CHECK(operand_types[i + 1] == OperandType::kRegCount);
- int reg_count = static_cast<int>(operands[i + 1]);
- if (reg_count == 0) {
- return Register::FromOperand(operands[i]) == Register(0);
- } else {
- Register start = Register::FromOperand(operands[i]);
- Register end(start.index() + reg_count - 1);
- if (!RegisterIsValid(start) || !RegisterIsValid(end) || start > end) {
- return false;
- }
- }
- i++; // Skip past kRegCount operand.
- break;
- }
- case OperandType::kReg:
- case OperandType::kRegOut: {
- Register reg = Register::FromOperand(operands[i]);
- if (!RegisterIsValid(reg)) {
- return false;
- }
- break;
- }
- case OperandType::kRegOutPair:
- case OperandType::kRegPair: {
- Register reg0 = Register::FromOperand(operands[i]);
- Register reg1 = Register(reg0.index() + 1);
- if (!RegisterIsValid(reg0) || !RegisterIsValid(reg1)) {
- return false;
- }
- break;
- }
- case OperandType::kRegOutTriple: {
- Register reg0 = Register::FromOperand(operands[i]);
- Register reg1 = Register(reg0.index() + 1);
- Register reg2 = Register(reg0.index() + 2);
- if (!RegisterIsValid(reg0) || !RegisterIsValid(reg1) ||
- !RegisterIsValid(reg2)) {
- return false;
- }
- break;
}
- case OperandType::kRegCount:
- UNREACHABLE(); // Dealt with in kRegList above.
}
+ return true;
}
+}
+
+void BytecodeArrayBuilder::PrepareToOutputBytecode(Bytecode bytecode) {
+ if (register_optimizer_) register_optimizer_->PrepareForBytecode(bytecode);
+}
+
+uint32_t BytecodeArrayBuilder::GetInputRegisterOperand(Register reg) {
+ DCHECK(RegisterIsValid(reg));
+ if (register_optimizer_) reg = register_optimizer_->GetInputRegister(reg);
+ return static_cast<uint32_t>(reg.ToOperand());
+}
+
+uint32_t BytecodeArrayBuilder::GetOutputRegisterOperand(Register reg) {
+ DCHECK(RegisterIsValid(reg));
+ if (register_optimizer_) register_optimizer_->PrepareOutputRegister(reg);
+ return static_cast<uint32_t>(reg.ToOperand());
+}
+
+uint32_t BytecodeArrayBuilder::GetInputRegisterListOperand(
+ RegisterList reg_list) {
+ DCHECK(RegisterListIsValid(reg_list));
+ if (register_optimizer_)
+ reg_list = register_optimizer_->GetInputRegisterList(reg_list);
+ return static_cast<uint32_t>(reg_list.first_register().ToOperand());
+}
- return true;
+uint32_t BytecodeArrayBuilder::GetOutputRegisterListOperand(
+ RegisterList reg_list) {
+ DCHECK(RegisterListIsValid(reg_list));
+ if (register_optimizer_)
+ register_optimizer_->PrepareOutputRegisterList(reg_list);
+ return static_cast<uint32_t>(reg_list.first_register().ToOperand());
}
} // namespace interpreter
« no previous file with comments | « src/interpreter/bytecode-array-builder.h ('k') | src/interpreter/bytecode-operands.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698