Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "src/interpreter/bytecode-array-builder.h" | |
| 6 | |
| 7 namespace v8 { | |
| 8 namespace internal { | |
| 9 namespace interpreter { | |
| 10 | |
| 11 BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate) | |
| 12 : isolate_(isolate), | |
| 13 bytecode_generated_(false), | |
| 14 local_register_count_(-1), | |
| 15 temporary_register_count_(0), | |
| 16 temporary_register_next_(0) {} | |
| 17 | |
| 18 | |
| 19 void BytecodeArrayBuilder::set_locals_count(int number_of_locals) { | |
| 20 local_register_count_ = number_of_locals; | |
| 21 temporary_register_next_ = local_register_count_; | |
| 22 } | |
| 23 | |
| 24 | |
| 25 int BytecodeArrayBuilder::locals_count() const { return local_register_count_; } | |
| 26 | |
| 27 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() { | |
| 28 DCHECK_EQ(bytecode_generated_, false); | |
| 29 DCHECK_GE(local_register_count_, 0); | |
| 30 int bytecode_size = static_cast<int>(bytecodes_.size()); | |
| 31 int register_count = local_register_count_ + temporary_register_count_; | |
| 32 int frame_size = register_count * kPointerSize; | |
| 33 Handle<BytecodeArray> output = isolate_->factory()->NewBytecodeArray( | |
| 34 bytecode_size, &bytecodes_.front(), frame_size); | |
| 35 bytecode_generated_ = true; | |
| 36 return output; | |
| 37 } | |
| 38 | |
| 39 | |
| 40 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value binop, | |
| 41 int reg) { | |
| 42 Output(BytecodeForBinaryOperation(binop), reg); | |
| 43 return *this; | |
| 44 } | |
| 45 | |
| 46 | |
| 47 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral( | |
| 48 v8::internal::Smi* smi) { | |
| 49 int32_t raw_smi = smi->value(); | |
| 50 if (raw_smi == 0) { | |
| 51 Output(Bytecode::kLdaZero); | |
| 52 } else if (raw_smi > -128 && raw_smi <= 128) { | |
| 53 Output(Bytecode::kLdaSmi8, static_cast<uint8_t>(raw_smi)); | |
| 54 } else { | |
| 55 // TODO(oth): Put Smi in constant pool. | |
| 56 UNIMPLEMENTED(); | |
| 57 } | |
| 58 return *this; | |
| 59 } | |
| 60 | |
| 61 | |
| 62 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() { | |
| 63 Output(Bytecode::kLdaUndefined); | |
| 64 return *this; | |
| 65 } | |
| 66 | |
| 67 | |
| 68 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() { | |
| 69 Output(Bytecode::kLdaNull); | |
| 70 return *this; | |
| 71 } | |
| 72 | |
| 73 | |
| 74 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() { | |
| 75 Output(Bytecode::kLdaTheHole); | |
| 76 return *this; | |
| 77 } | |
| 78 | |
| 79 | |
| 80 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() { | |
| 81 Output(Bytecode::kLdaTrue); | |
| 82 return *this; | |
| 83 } | |
| 84 | |
| 85 | |
| 86 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() { | |
| 87 Output(Bytecode::kLdaFalse); | |
| 88 return *this; | |
| 89 } | |
| 90 | |
| 91 | |
| 92 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister( | |
| 93 int reg) { | |
| 94 Output(Bytecode::kLdar, reg); | |
| 95 return *this; | |
| 96 } | |
| 97 | |
| 98 | |
| 99 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister( | |
| 100 int reg) { | |
| 101 Output(Bytecode::kStar, reg); | |
| 102 return *this; | |
| 103 } | |
| 104 | |
| 105 | |
| 106 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() { | |
| 107 Output(Bytecode::kReturn); | |
| 108 return *this; | |
| 109 } | |
| 110 | |
| 111 | |
| 112 int BytecodeArrayBuilder::BorrowTemporaryRegister() { | |
| 113 DCHECK_GE(local_register_count_, 0); | |
| 114 int temporary_register = temporary_register_next_++; | |
| 115 int count = temporary_register_next_ - local_register_count_; | |
| 116 if (count > temporary_register_count_) { | |
| 117 temporary_register_count_ = count; | |
| 118 } | |
| 119 return temporary_register; | |
| 120 } | |
| 121 | |
| 122 | |
| 123 void BytecodeArrayBuilder::ReturnTemporaryRegister(int reg) { | |
| 124 DCHECK_EQ(reg, temporary_register_next_ - 1); | |
| 125 temporary_register_next_ = reg; | |
| 126 } | |
| 127 | |
| 128 | |
| 129 bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index, | |
| 130 uint8_t operand_value) const { | |
| 131 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index); | |
| 132 switch (operand_type) { | |
| 133 case OperandType::kNone: | |
| 134 return false; | |
| 135 case OperandType::kImm8: | |
| 136 return true; | |
| 137 case OperandType::kReg: | |
| 138 return operand_value < temporary_register_next_; | |
| 139 } | |
| 140 UNREACHABLE(); | |
| 141 return false; | |
| 142 } | |
| 143 | |
| 144 | |
| 145 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0, | |
| 146 uint8_t operand1, uint8_t operand2) { | |
| 147 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 3); | |
|
picksi
2015/08/03 11:06:01
This function does a DCHECK_EQ, the following func
oth
2015/08/03 15:39:59
Fixed, thanks!
| |
| 148 DCHECK(OperandIsValid(bytecode, 0, operand0) && | |
| 149 OperandIsValid(bytecode, 1, operand1) && | |
| 150 OperandIsValid(bytecode, 2, operand2)); | |
| 151 bytecodes_.push_back(Bytecodes::ToByte(bytecode)); | |
| 152 bytecodes_.push_back(operand0); | |
| 153 bytecodes_.push_back(operand1); | |
| 154 bytecodes_.push_back(operand2); | |
| 155 } | |
| 156 | |
| 157 | |
| 158 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0, | |
| 159 uint8_t operand1) { | |
| 160 DCHECK(Bytecodes::NumberOfOperands(bytecode) == 2); | |
| 161 DCHECK(OperandIsValid(bytecode, 0, operand0) && | |
| 162 OperandIsValid(bytecode, 1, operand1)); | |
| 163 bytecodes_.push_back(Bytecodes::ToByte(bytecode)); | |
| 164 bytecodes_.push_back(operand0); | |
| 165 bytecodes_.push_back(operand1); | |
| 166 } | |
| 167 | |
| 168 | |
| 169 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0) { | |
| 170 DCHECK(Bytecodes::NumberOfOperands(bytecode) == 1); | |
| 171 DCHECK(OperandIsValid(bytecode, 0, operand0)); | |
| 172 bytecodes_.push_back(Bytecodes::ToByte(bytecode)); | |
| 173 bytecodes_.push_back(operand0); | |
| 174 } | |
| 175 | |
| 176 | |
| 177 void BytecodeArrayBuilder::Output(Bytecode bytecode) { | |
| 178 DCHECK(Bytecodes::NumberOfOperands(bytecode) == 0); | |
| 179 bytecodes_.push_back(Bytecodes::ToByte(bytecode)); | |
| 180 } | |
| 181 | |
| 182 | |
| 183 // static | |
| 184 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) { | |
| 185 switch (op) { | |
| 186 case Token::Value::ADD: | |
| 187 return Bytecode::kAdd; | |
| 188 case Token::Value::SUB: | |
| 189 return Bytecode::kSub; | |
| 190 case Token::Value::MUL: | |
| 191 return Bytecode::kMul; | |
| 192 case Token::Value::DIV: | |
| 193 return Bytecode::kDiv; | |
| 194 default: | |
| 195 UNIMPLEMENTED(); | |
| 196 return static_cast<Bytecode>(-1); | |
|
picksi
2015/08/03 11:06:01
Should we have an error ByteCode that is -1, inste
oth
2015/08/03 15:39:59
In this instance, it's not recoverable error. The
| |
| 197 } | |
| 198 } | |
| 199 | |
| 200 | |
| 201 TemporaryRegisterScope::TemporaryRegisterScope(BytecodeArrayBuilder* builder) | |
| 202 : builder_(builder), count_(0), register_(-1) {} | |
| 203 | |
| 204 | |
| 205 TemporaryRegisterScope::~TemporaryRegisterScope() { | |
| 206 while (count_-- != 0) { | |
| 207 builder_->ReturnTemporaryRegister(register_--); | |
| 208 } | |
| 209 } | |
| 210 | |
| 211 | |
| 212 int TemporaryRegisterScope::NewRegister() { | |
| 213 count_++; | |
| 214 register_ = builder_->BorrowTemporaryRegister(); | |
| 215 return register_; | |
| 216 } | |
| 217 | |
| 218 } // namespace interpreter | |
| 219 } // namespace internal | |
| 220 } // namespace v8 | |
| OLD | NEW |