Commit a7e16e51 authored by oth's avatar oth Committed by Commit bot

[Interpreter] Add for/while/do support to the bytecode generator.

Improve bytecode generation for if when there's no else clause.

Display target addresses for jump instructions in
Bytecode::Disassemble().

BUG=v8:4280
LOG=N

Review URL: https://codereview.chromium.org/1373903005

Cr-Commit-Position: refs/heads/master@{#31052}
parent cf82eea6
......@@ -1051,6 +1051,8 @@ source_set("v8_base") {
"src/interpreter/bytecode-array-iterator.h",
"src/interpreter/bytecode-generator.cc",
"src/interpreter/bytecode-generator.h",
"src/interpreter/control-flow-builders.cc",
"src/interpreter/control-flow-builders.h",
"src/interpreter/interpreter.cc",
"src/interpreter/interpreter.h",
"src/isolate-inl.h",
......
......@@ -10,6 +10,7 @@ namespace interpreter {
BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone)
: isolate_(isolate),
zone_(zone),
bytecodes_(zone),
bytecode_generated_(false),
last_block_end_(0),
......@@ -314,11 +315,14 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) {
}
// static
bool BytecodeArrayBuilder::IsJumpWithImm8Operand(Bytecode jump_bytecode) {
return jump_bytecode == Bytecode::kJump ||
jump_bytecode == Bytecode::kJumpIfTrue ||
jump_bytecode == Bytecode::kJumpIfFalse;
BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target,
BytecodeLabel* label) {
DCHECK_EQ(label->is_bound(), false);
DCHECK_EQ(target.is_bound(), true);
PatchJump(bytecodes()->begin() + target.offset(),
bytecodes()->begin() + label->offset());
label->bind_to(target.offset());
return *this;
}
......@@ -345,9 +349,9 @@ void BytecodeArrayBuilder::PatchJump(
Bytecode jump_bytecode = Bytecodes::FromByte(*jump_location);
int delta = static_cast<int>(jump_target - jump_location);
DCHECK(IsJumpWithImm8Operand(jump_bytecode));
DCHECK(Bytecodes::IsJump(jump_bytecode));
DCHECK_EQ(Bytecodes::Size(jump_bytecode), 2);
DCHECK_GE(delta, 0);
DCHECK_NE(delta, 0);
if (FitsInImm8Operand(delta)) {
// Just update the operand
......@@ -357,8 +361,8 @@ void BytecodeArrayBuilder::PatchJump(
// Update the jump type and operand
size_t entry = GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate()));
if (FitsInIdxOperand(entry)) {
*jump_location++ =
Bytecodes::ToByte(GetJumpWithConstantOperand(jump_bytecode));
jump_bytecode = GetJumpWithConstantOperand(jump_bytecode);
*jump_location++ = Bytecodes::ToByte(jump_bytecode);
*jump_location = static_cast<uint8_t>(entry);
} else {
// TODO(oth): OutputJump should reserve a constant pool entry
......
......@@ -87,6 +87,8 @@ class BytecodeArrayBuilder {
// Flow Control.
BytecodeArrayBuilder& Bind(BytecodeLabel* label);
BytecodeArrayBuilder& Bind(const BytecodeLabel& target, BytecodeLabel* label);
BytecodeArrayBuilder& Jump(BytecodeLabel* label);
BytecodeArrayBuilder& JumpIfTrue(BytecodeLabel* label);
BytecodeArrayBuilder& JumpIfFalse(BytecodeLabel* label);
......@@ -95,6 +97,9 @@ class BytecodeArrayBuilder {
BytecodeArrayBuilder& EnterBlock();
BytecodeArrayBuilder& LeaveBlock();
// Accessors
Zone* zone() const { return zone_; }
private:
ZoneVector<uint8_t>* bytecodes() { return &bytecodes_; }
const ZoneVector<uint8_t>* bytecodes() const { return &bytecodes_; }
......@@ -105,7 +110,6 @@ class BytecodeArrayBuilder {
static bool FitsInIdxOperand(int value);
static bool FitsInIdxOperand(size_t value);
static bool FitsInImm8Operand(int value);
static bool IsJumpWithImm8Operand(Bytecode jump_bytecode);
static Bytecode GetJumpWithConstantOperand(Bytecode jump_with_smi8_operand);
template <size_t N>
......@@ -133,6 +137,7 @@ class BytecodeArrayBuilder {
void ReturnTemporaryRegister(int reg_index);
Isolate* isolate_;
Zone* zone_;
ZoneVector<uint8_t> bytecodes_;
bool bytecode_generated_;
size_t last_block_end_;
......@@ -159,7 +164,6 @@ class BytecodeArrayBuilder {
class BytecodeLabel final {
public:
BytecodeLabel() : bound_(false), offset_(kInvalidOffset) {}
~BytecodeLabel() { DCHECK(bound_ && offset_ != kInvalidOffset); }
private:
static const size_t kInvalidOffset = static_cast<size_t>(-1);
......@@ -188,7 +192,6 @@ class BytecodeLabel final {
size_t offset_;
friend class BytecodeArrayBuilder;
DISALLOW_COPY_AND_ASSIGN(BytecodeLabel);
};
......
This diff is collapsed.
......@@ -25,15 +25,20 @@ class BytecodeGenerator : public AstVisitor {
#undef DECLARE_VISIT
private:
class ControlScope;
class ControlScopeForIteration;
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
void VisitArithmeticExpression(BinaryOperation* binop);
void VisitPropertyLoad(Register obj, Property* expr);
void VisitVariableLoad(Variable* variable);
inline BytecodeArrayBuilder& builder() { return builder_; }
inline BytecodeArrayBuilder* builder() { return &builder_; }
inline Scope* scope() const { return scope_; }
inline void set_scope(Scope* scope) { scope_ = scope; }
inline ControlScope* control_scope() const { return control_scope_; }
inline void set_control_scope(ControlScope* scope) { control_scope_ = scope; }
inline CompilationInfo* info() const { return info_; }
inline void set_info(CompilationInfo* info) { info_ = info; }
......@@ -43,6 +48,7 @@ class BytecodeGenerator : public AstVisitor {
BytecodeArrayBuilder builder_;
CompilationInfo* info_;
Scope* scope_;
ControlScope* control_scope_;
};
} // namespace interpreter
......
......@@ -102,6 +102,21 @@ int Bytecodes::MaximumNumberOfOperands() { return kMaxOperands; }
int Bytecodes::MaximumSize() { return 1 + kMaxOperands; }
// static
bool Bytecodes::IsJump(Bytecode bytecode) {
return bytecode == Bytecode::kJump || bytecode == Bytecode::kJumpIfTrue ||
bytecode == Bytecode::kJumpIfFalse;
}
// static
bool Bytecodes::IsJumpConstant(Bytecode bytecode) {
return bytecode == Bytecode::kJumpConstant ||
bytecode == Bytecode::kJumpIfTrueConstant ||
bytecode == Bytecode::kJumpIfFalseConstant;
}
// static
std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start,
int parameter_count) {
......
......@@ -178,6 +178,14 @@ class Bytecodes {
// Maximum size of a bytecode and its operands.
static int MaximumSize();
// Return true if the bytecode is a jump or a conditional jump taking
// an immediate byte operand (OperandType::kImm8).
static bool IsJump(Bytecode bytecode);
// Return true if the bytecode is a jump or conditional jump taking a
// constant pool entry (OperandType::kIdx).
static bool IsJumpConstant(Bytecode bytecode);
// Decode a single bytecode and operands to |os|.
static std::ostream& Decode(std::ostream& os, const uint8_t* bytecode_start,
int number_of_parameters);
......
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/interpreter/control-flow-builders.h"
namespace v8 {
namespace internal {
namespace interpreter {
LoopBuilder::~LoopBuilder() {
DCHECK(continue_sites_.empty());
DCHECK(break_sites_.empty());
}
void LoopBuilder::SetContinueTarget(const BytecodeLabel& target) {
BindLabels(target, &continue_sites_);
}
void LoopBuilder::SetBreakTarget(const BytecodeLabel& target) {
BindLabels(target, &break_sites_);
}
void LoopBuilder::EmitJump(ZoneVector<BytecodeLabel>* sites) {
sites->push_back(BytecodeLabel());
builder()->Jump(&sites->back());
}
void LoopBuilder::BindLabels(const BytecodeLabel& target,
ZoneVector<BytecodeLabel>* sites) {
for (size_t i = 0; i < sites->size(); i++) {
BytecodeLabel& site = sites->at(i);
builder()->Bind(target, &site);
}
sites->clear();
}
} // namespace interpreter
} // namespace internal
} // namespace v8
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_INTERPRETER_CONTROL_FLOW_BUILDERS_H_
#define V8_INTERPRETER_CONTROL_FLOW_BUILDERS_H_
#include "src/interpreter/bytecode-array-builder.h"
#include "src/zone-containers.h"
namespace v8 {
namespace internal {
namespace interpreter {
class ControlFlowBuilder BASE_EMBEDDED {
public:
explicit ControlFlowBuilder(BytecodeArrayBuilder* builder)
: builder_(builder) {}
virtual ~ControlFlowBuilder() {}
protected:
BytecodeArrayBuilder* builder() const { return builder_; }
private:
BytecodeArrayBuilder* builder_;
DISALLOW_COPY_AND_ASSIGN(ControlFlowBuilder);
};
// A class to help with co-ordinating break and continue statements with
// their loop.
// TODO(oth): add support for TF branch/merge info.
class LoopBuilder : public ControlFlowBuilder {
public:
explicit LoopBuilder(BytecodeArrayBuilder* builder)
: ControlFlowBuilder(builder),
continue_sites_(builder->zone()),
break_sites_(builder->zone()) {}
~LoopBuilder();
// These methods should be called by the LoopBuilder owner before
// destruction to update sites that emit jumps for break/continue.
void SetContinueTarget(const BytecodeLabel& continue_target);
void SetBreakTarget(const BytecodeLabel& break_target);
// These methods are called when visiting break and continue
// statements in the AST. Inserts a jump to a unbound label that is
// patched when the corresponding SetContinueTarget/SetBreakTarget
// is called.
void Break() { EmitJump(&break_sites_); }
void Continue() { EmitJump(&continue_sites_); }
private:
void BindLabels(const BytecodeLabel& target, ZoneVector<BytecodeLabel>* site);
void EmitJump(ZoneVector<BytecodeLabel>* labels);
// Unbound labels that identify jumps for continue/break statements
// in the code.
ZoneVector<BytecodeLabel> continue_sites_;
ZoneVector<BytecodeLabel> break_sites_;
};
} // namespace interpreter
} // namespace internal
} // namespace v8
#endif // V8_INTERPRETER_CONTROL_FLOW_BUILDERS_H_
......@@ -12557,6 +12557,16 @@ void BytecodeArray::Disassemble(std::ostream& os) {
SNPrintF(buf, "%p", bytecode_start);
os << buf.start() << " : ";
interpreter::Bytecodes::Decode(os, bytecode_start, parameter_count());
if (interpreter::Bytecodes::IsJump(bytecode)) {
int offset = static_cast<int8_t>(bytecode_start[1]);
SNPrintF(buf, " (%p)", bytecode_start + offset);
os << buf.start();
} else if (interpreter::Bytecodes::IsJumpConstant(bytecode)) {
int index = static_cast<int>(bytecode_start[1]);
int offset = Smi::cast(constant_pool()->get(index))->value();
SNPrintF(buf, " (%p)", bytecode_start + offset);
os << buf.start();
}
os << "\n";
}
......
......@@ -816,6 +816,8 @@
'../../src/interpreter/bytecode-array-builder.h',
'../../src/interpreter/bytecode-array-iterator.cc',
'../../src/interpreter/bytecode-array-iterator.h',
'../../src/interpreter/control-flow-builders.cc',
'../../src/interpreter/control-flow-builders.h',
'../../src/interpreter/interpreter.cc',
'../../src/interpreter/interpreter.h',
'../../src/isolate-inl.h',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment