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

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

Issue 1343363002: [Interpreter] Basic flow control. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Clarify comment and diff reduction. Created 5 years, 3 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
Index: src/interpreter/bytecode-array-builder.cc
diff --git a/src/interpreter/bytecode-array-builder.cc b/src/interpreter/bytecode-array-builder.cc
index f3a1b1ea0803959990370da458ae10da87d8ec54..791ab5a1517a75535ae6fb76e4add31eace79c49 100644
--- a/src/interpreter/bytecode-array-builder.cc
+++ b/src/interpreter/bytecode-array-builder.cc
@@ -14,6 +14,8 @@ BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone)
bytecode_generated_(false),
constants_map_(isolate->heap(), zone),
constants_(zone),
+ forward_labels_(zone),
+ bound_labels_(zone),
parameter_count_(-1),
local_register_count_(-1),
temporary_register_count_(0),
@@ -76,9 +78,90 @@ Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() {
}
-BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value binop,
+template <size_t N>
+void BytecodeArrayBuilder::RawOutputAt(ZoneVector<uint8_t>::iterator pos,
+ uint8_t(&bytes)[N]) {
+ DCHECK_EQ(Bytecodes::NumberOfOperands(Bytecodes::FromByte(bytes[0])), N - 1);
+ for (int i = 1; i < static_cast<int>(N); i++) {
+ DCHECK(OperandIsValid(Bytecodes::FromByte(bytes[0]), i - 1, bytes[i]));
+ }
+
+ if (bytecodes()->end() == pos) {
rmcilroy 2015/09/18 10:42:23 I'm not keen on having the Output operators do pat
oth 2015/09/23 10:46:55 Done.
+ bytecodes()->insert(pos, bytes, bytes + N);
+ } else {
+ std::copy(bytes, bytes + N, pos);
+ }
+}
+
+
+void BytecodeArrayBuilder::Output(const ZoneVector<uint8_t>::iterator& pos,
+ Bytecode bytecode, uint8_t operand0) {
+ uint8_t bytes[] = {Bytecodes::ToByte(bytecode), operand0};
+ RawOutputAt(pos, bytes);
+}
+
+
+void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0,
+ uint8_t operand1, uint8_t operand2) {
+ uint8_t bytes[] = {Bytecodes::ToByte(bytecode), operand0, operand1, operand2};
+ RawOutputAt(bytecodes()->end(), bytes);
+}
+
+
+void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0,
+ uint8_t operand1) {
+ uint8_t bytes[] = {Bytecodes::ToByte(bytecode), operand0, operand1};
+ RawOutputAt(bytecodes()->end(), bytes);
+}
+
+
+void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0) {
+ uint8_t bytes[] = {Bytecodes::ToByte(bytecode), operand0};
+ RawOutputAt(bytecodes()->end(), bytes);
+}
+
+
+void BytecodeArrayBuilder::Output(Bytecode bytecode) {
+ uint8_t bytes[] = {Bytecodes::ToByte(bytecode)};
+ RawOutputAt(bytecodes()->end(), bytes);
+}
+
+
+BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
Register reg) {
- Output(BytecodeForBinaryOperation(binop), reg.ToOperand());
+ Output(BytecodeForBinaryOperation(op), reg.ToOperand());
+ return *this;
+}
+
+
+BytecodeArrayBuilder& BytecodeArrayBuilder::Add(Register reg) {
+ return BinaryOperation(Token::Value::ADD, reg);
+}
+
+
+BytecodeArrayBuilder& BytecodeArrayBuilder::Subtract(Register reg) {
+ return BinaryOperation(Token::Value::SUB, reg);
+}
+
+
+BytecodeArrayBuilder& BytecodeArrayBuilder::Multiply(Register reg) {
+ return BinaryOperation(Token::Value::MUL, reg);
+}
+
+
+BytecodeArrayBuilder& BytecodeArrayBuilder::Divide(Register reg) {
+ return BinaryOperation(Token::Value::DIV, reg);
+}
+
+
+BytecodeArrayBuilder& BytecodeArrayBuilder::Modulo(Register reg) {
+ return BinaryOperation(Token::Value::MOD, reg);
+}
+
+
+BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(Token::Value op,
+ Register reg) {
+ Output(BytecodeForCompareOperation(op), reg.ToOperand());
return *this;
}
@@ -99,7 +182,7 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) {
size_t entry = GetConstantPoolEntry(object);
- if (FitsInByteOperand(entry)) {
+ if (FitsInIdxOperand(entry)) {
Output(Bytecode::kLdaConstant, static_cast<uint8_t>(entry));
} else {
UNIMPLEMENTED();
@@ -108,6 +191,21 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) {
}
+BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(int value) {
+ Handle<Object> v = isolate()->factory()->NewNumberFromInt(value);
+ if (v->IsSmi()) {
+ return LoadLiteral(Smi::cast(*v));
+ } else {
+ return LoadLiteral(v);
+ }
+}
+
+
+BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(double value) {
+ return LoadLiteral(isolate()->factory()->NewNumber(value));
+}
+
+
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() {
Output(Bytecode::kLdaUndefined);
return *this;
@@ -158,7 +256,7 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
UNIMPLEMENTED();
}
- if (FitsInByteOperand(feedback_slot)) {
+ if (FitsInIdxOperand(feedback_slot)) {
Output(Bytecode::kLoadIC, object.ToOperand(),
static_cast<uint8_t>(feedback_slot));
} else {
@@ -174,7 +272,7 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
UNIMPLEMENTED();
}
- if (FitsInByteOperand(feedback_slot)) {
+ if (FitsInIdxOperand(feedback_slot)) {
Output(Bytecode::kKeyedLoadIC, object.ToOperand(),
static_cast<uint8_t>(feedback_slot));
} else {
@@ -191,7 +289,7 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
UNIMPLEMENTED();
}
- if (FitsInByteOperand(feedback_slot)) {
+ if (FitsInIdxOperand(feedback_slot)) {
Output(Bytecode::kStoreIC, object.ToOperand(), name.ToOperand(),
static_cast<uint8_t>(feedback_slot));
} else {
@@ -208,7 +306,7 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty(
UNIMPLEMENTED();
}
- if (FitsInByteOperand(feedback_slot)) {
+ if (FitsInIdxOperand(feedback_slot)) {
Output(Bytecode::kKeyedStoreIC, object.ToOperand(), key.ToOperand(),
static_cast<uint8_t>(feedback_slot));
} else {
@@ -218,6 +316,101 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty(
}
+BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) {
+ auto forward_labels_iterator = forward_labels_.find(label);
+ if (forward_labels_.end() != forward_labels_iterator) {
+ // Label is forward referred to, update the referring jump instruction.
+ ZoneVector<uint8_t>::iterator it = bytecodes()->begin() + label->offset();
+ OutputJump(Bytecodes::FromByte(*it), it, bytecodes()->end());
+ forward_labels_.erase(forward_labels_iterator);
+ // Now treat as if the label will only be back referred to.
+ }
+
+ DCHECK(bound_labels_.end() == bound_labels_.find(label));
+ label->bind_to(bytecodes()->size());
+ bound_labels_.insert(label);
+ return *this;
+}
+
+
+// static
+bool BytecodeArrayBuilder::IsJumpWithSmi8Operand(Bytecode jump_bytecode) {
+ return jump_bytecode == Bytecode::kJumpSmi8 ||
+ jump_bytecode == Bytecode::kJumpIfTrueSmi8 ||
+ jump_bytecode == Bytecode::kJumpIfFalseSmi8;
+}
+
+
+// static
+Bytecode BytecodeArrayBuilder::GetJumpWithConstantOperand(
+ Bytecode jump_bytecode) {
+ switch (jump_bytecode) {
+ case Bytecode::kJumpSmi8:
+ return Bytecode::kJumpConstant;
+ case Bytecode::kJumpIfTrueSmi8:
+ return Bytecode::kJumpIfTrueConstant;
+ case Bytecode::kJumpIfFalseSmi8:
+ return Bytecode::kJumpIfFalseConstant;
+ default:
+ UNREACHABLE();
+ return Bytecode::kJumpConstant;
+ }
+}
+
+
+void BytecodeArrayBuilder::OutputJump(
+ Bytecode jump_bytecode, const ZoneVector<uint8_t>::iterator& jump_location,
+ const ZoneVector<uint8_t>::iterator& jump_target) {
+ DCHECK(IsJumpWithSmi8Operand(jump_bytecode));
+
+ int delta = static_cast<int>(jump_target - jump_location);
+ if (FitsInImm8Operand(delta)) {
+ Output(jump_location, jump_bytecode, static_cast<uint8_t>(delta));
+ } else {
+ size_t entry = GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate()));
+ if (FitsInIdxOperand(entry)) {
+ jump_bytecode = GetJumpWithConstantOperand(jump_bytecode);
+ Output(jump_location, jump_bytecode, static_cast<uint8_t>(entry));
+ } else {
+ UNIMPLEMENTED();
+ }
+ }
+}
+
+
+BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(Bytecode jump_bytecode,
+ BytecodeLabel* label) {
+ if (bound_labels_.find(label) != bound_labels_.end()) {
+ // Label has been bound already so this is a backwards jump.
+ OutputJump(jump_bytecode, bytecodes()->end(),
+ bytecodes()->begin() + label->offset());
+ } else {
+ // Label has not yet been bound so this is a forward reference
+ // that will be patched when the label is bound.
+ DCHECK(forward_labels_.find(label) == forward_labels_.end());
+ label->bind_to(bytecodes()->size());
+ forward_labels_.insert(label);
+ OutputJump(jump_bytecode, bytecodes()->end(), bytecodes()->end());
+ }
+ return *this;
+}
+
+
+BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
+ return Jump(Bytecode::kJumpSmi8, label);
+}
+
+
+BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) {
+ return Jump(Bytecode::kJumpIfTrueSmi8, label);
+}
+
+
+BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) {
+ return Jump(Bytecode::kJumpIfFalseSmi8, label);
+}
+
+
BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
Output(Bytecode::kReturn);
return *this;
@@ -227,7 +420,7 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable,
Register receiver,
size_t arg_count) {
- if (FitsInByteOperand(arg_count)) {
+ if (FitsInIdxOperand(arg_count)) {
Output(Bytecode::kCall, callable.ToOperand(), receiver.ToOperand(),
static_cast<uint8_t>(arg_count));
} else {
@@ -299,44 +492,6 @@ bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index,
}
-void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0,
- uint8_t operand1, uint8_t operand2) {
- DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 3);
- DCHECK(OperandIsValid(bytecode, 0, operand0) &&
- OperandIsValid(bytecode, 1, operand1) &&
- OperandIsValid(bytecode, 2, operand2));
- bytecodes_.push_back(Bytecodes::ToByte(bytecode));
- bytecodes_.push_back(operand0);
- bytecodes_.push_back(operand1);
- bytecodes_.push_back(operand2);
-}
-
-
-void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0,
- uint8_t operand1) {
- DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 2);
- DCHECK(OperandIsValid(bytecode, 0, operand0) &&
- OperandIsValid(bytecode, 1, operand1));
- bytecodes_.push_back(Bytecodes::ToByte(bytecode));
- bytecodes_.push_back(operand0);
- bytecodes_.push_back(operand1);
-}
-
-
-void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0) {
- DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 1);
- DCHECK(OperandIsValid(bytecode, 0, operand0));
- bytecodes_.push_back(Bytecodes::ToByte(bytecode));
- bytecodes_.push_back(operand0);
-}
-
-
-void BytecodeArrayBuilder::Output(Bytecode bytecode) {
- DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0);
- bytecodes_.push_back(Bytecodes::ToByte(bytecode));
-}
-
-
// static
Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) {
switch (op) {
@@ -358,17 +513,53 @@ Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) {
// static
-bool BytecodeArrayBuilder::FitsInByteOperand(int value) {
+Bytecode BytecodeArrayBuilder::BytecodeForCompareOperation(Token::Value op) {
+ switch (op) {
+ case Token::Value::EQ:
+ return Bytecode::kTestEqual;
+ case Token::Value::NE:
+ return Bytecode::kTestNotEqual;
+ case Token::Value::EQ_STRICT:
+ return Bytecode::kTestEqualStrict;
+ case Token::Value::NE_STRICT:
+ return Bytecode::kTestNotEqualStrict;
+ case Token::Value::LT:
+ return Bytecode::kTestLessThan;
+ case Token::Value::GT:
+ return Bytecode::kTestGreaterThan;
+ case Token::Value::LTE:
+ return Bytecode::kTestLessThanEqual;
+ case Token::Value::GTE:
+ return Bytecode::kTestGreaterThanEqual;
+ case Token::Value::INSTANCEOF:
+ return Bytecode::kTestInstanceOf;
+ case Token::Value::IN:
+ return Bytecode::kTestIn;
+ default:
+ UNIMPLEMENTED();
+ return static_cast<Bytecode>(-1);
+ }
+}
+
+
+// static
+bool BytecodeArrayBuilder::FitsInIdxOperand(int value) {
return 0 <= value && value <= 255;
}
// static
-bool BytecodeArrayBuilder::FitsInByteOperand(size_t value) {
+bool BytecodeArrayBuilder::FitsInIdxOperand(size_t value) {
return value <= 255;
}
+// static
+bool BytecodeArrayBuilder::FitsInImm8Operand(int value) {
+ return -128 <= value && value < 127;
+}
+
+
TemporaryRegisterScope::TemporaryRegisterScope(BytecodeArrayBuilder* builder)
: builder_(builder), count_(0), last_register_index_(-1) {}

Powered by Google App Engine
This is Rietveld 408576698