| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/interpreter/bytecode-array-builder.h" | 5 #include "src/interpreter/bytecode-array-builder.h" |
| 6 | 6 |
| 7 #include "src/globals.h" | 7 #include "src/globals.h" |
| 8 #include "src/interpreter/bytecode-array-writer.h" | 8 #include "src/interpreter/bytecode-array-writer.h" |
| 9 #include "src/interpreter/bytecode-dead-code-optimizer.h" | 9 #include "src/interpreter/bytecode-dead-code-optimizer.h" |
| 10 #include "src/interpreter/bytecode-label.h" | 10 #include "src/interpreter/bytecode-label.h" |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 bytecode_generated_(false), | 24 bytecode_generated_(false), |
| 25 constant_array_builder_(zone, isolate->factory()->the_hole_value()), | 25 constant_array_builder_(zone, isolate->factory()->the_hole_value()), |
| 26 handler_table_builder_(zone), | 26 handler_table_builder_(zone), |
| 27 return_seen_in_block_(false), | 27 return_seen_in_block_(false), |
| 28 parameter_count_(parameter_count), | 28 parameter_count_(parameter_count), |
| 29 local_register_count_(locals_count), | 29 local_register_count_(locals_count), |
| 30 context_register_count_(context_count), | 30 context_register_count_(context_count), |
| 31 register_allocator_(fixed_register_count()), | 31 register_allocator_(fixed_register_count()), |
| 32 bytecode_array_writer_(zone, &constant_array_builder_, | 32 bytecode_array_writer_(zone, &constant_array_builder_, |
| 33 source_position_mode), | 33 source_position_mode), |
| 34 pipeline_(&bytecode_array_writer_) { | 34 pipeline_(&bytecode_array_writer_), |
| 35 register_optimizer_(nullptr) { |
| 35 DCHECK_GE(parameter_count_, 0); | 36 DCHECK_GE(parameter_count_, 0); |
| 36 DCHECK_GE(context_register_count_, 0); | 37 DCHECK_GE(context_register_count_, 0); |
| 37 DCHECK_GE(local_register_count_, 0); | 38 DCHECK_GE(local_register_count_, 0); |
| 38 | 39 |
| 39 if (FLAG_ignition_deadcode) { | 40 if (FLAG_ignition_deadcode) { |
| 40 pipeline_ = new (zone) BytecodeDeadCodeOptimizer(pipeline_); | 41 pipeline_ = new (zone) BytecodeDeadCodeOptimizer(pipeline_); |
| 41 } | 42 } |
| 42 | 43 |
| 43 if (FLAG_ignition_peephole) { | 44 if (FLAG_ignition_peephole) { |
| 44 pipeline_ = new (zone) BytecodePeepholeOptimizer(pipeline_); | 45 pipeline_ = new (zone) BytecodePeepholeOptimizer(pipeline_); |
| 45 } | 46 } |
| 46 | 47 |
| 47 if (FLAG_ignition_reo) { | 48 if (FLAG_ignition_reo) { |
| 48 pipeline_ = new (zone) BytecodeRegisterOptimizer( | 49 register_optimizer_ = new (zone) BytecodeRegisterOptimizer( |
| 49 zone, ®ister_allocator_, fixed_register_count(), parameter_count, | 50 zone, ®ister_allocator_, fixed_register_count(), parameter_count, |
| 50 pipeline_); | 51 pipeline_); |
| 51 } | 52 } |
| 52 | 53 |
| 53 return_position_ = | 54 return_position_ = |
| 54 literal ? std::max(literal->start_position(), literal->end_position() - 1) | 55 literal ? std::max(literal->start_position(), literal->end_position() - 1) |
| 55 : kNoSourcePosition; | 56 : kNoSourcePosition; |
| 56 } | 57 } |
| 57 | 58 |
| 58 Register BytecodeArrayBuilder::first_context_register() const { | 59 Register BytecodeArrayBuilder::first_context_register() const { |
| 59 DCHECK_GT(context_register_count_, 0); | 60 DCHECK_GT(context_register_count_, 0); |
| 60 return Register(local_register_count_); | 61 return Register(local_register_count_); |
| 61 } | 62 } |
| 62 | 63 |
| 63 Register BytecodeArrayBuilder::last_context_register() const { | 64 Register BytecodeArrayBuilder::last_context_register() const { |
| 64 DCHECK_GT(context_register_count_, 0); | 65 DCHECK_GT(context_register_count_, 0); |
| 65 return Register(local_register_count_ + context_register_count_ - 1); | 66 return Register(local_register_count_ + context_register_count_ - 1); |
| 66 } | 67 } |
| 67 | 68 |
| 68 Register BytecodeArrayBuilder::Parameter(int parameter_index) const { | 69 Register BytecodeArrayBuilder::Parameter(int parameter_index) const { |
| 69 DCHECK_GE(parameter_index, 0); | 70 DCHECK_GE(parameter_index, 0); |
| 70 return Register::FromParameterIndex(parameter_index, parameter_count()); | 71 return Register::FromParameterIndex(parameter_index, parameter_count()); |
| 71 } | 72 } |
| 72 | 73 |
| 73 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) { | 74 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) { |
| 74 DCHECK(return_seen_in_block_); | 75 DCHECK(return_seen_in_block_); |
| 75 DCHECK(!bytecode_generated_); | 76 DCHECK(!bytecode_generated_); |
| 76 bytecode_generated_ = true; | 77 bytecode_generated_ = true; |
| 77 | 78 |
| 79 int register_count = total_register_count(); |
| 80 |
| 81 if (register_optimizer_) { |
| 82 register_optimizer_->Flush(); |
| 83 register_count = register_optimizer_->maxiumum_register_index() + 1; |
| 84 } |
| 85 |
| 78 Handle<FixedArray> handler_table = | 86 Handle<FixedArray> handler_table = |
| 79 handler_table_builder()->ToHandlerTable(isolate); | 87 handler_table_builder()->ToHandlerTable(isolate); |
| 80 return pipeline_->ToBytecodeArray(isolate, total_register_count(), | 88 return pipeline_->ToBytecodeArray(isolate, register_count, parameter_count(), |
| 81 parameter_count(), handler_table); | 89 handler_table); |
| 82 } | 90 } |
| 83 | 91 |
| 84 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | 92 BytecodeSourceInfo BytecodeArrayBuilder::CurrentSourcePosition( |
| 85 uint32_t operand1, uint32_t operand2, | 93 Bytecode bytecode) { |
| 86 uint32_t operand3) { | 94 BytecodeSourceInfo source_position; |
| 87 DCHECK(OperandsAreValid(bytecode, 4, operand0, operand1, operand2, operand3)); | 95 if (latest_source_info_.is_valid()) { |
| 88 BytecodeNode node(bytecode, operand0, operand1, operand2, operand3, | 96 // Statement positions need to be emitted immediately. Expression |
| 89 &latest_source_info_); | 97 // positions can be pushed back until a bytecode is found that can |
| 90 pipeline()->Write(&node); | 98 // throw (if expression position filtering is turned on). We only |
| 99 // invalidate the existing source position information if it is used. |
| 100 if (latest_source_info_.is_statement() || |
| 101 !FLAG_ignition_filter_expression_positions || |
| 102 !Bytecodes::IsWithoutExternalSideEffects(bytecode)) { |
| 103 source_position = latest_source_info_; |
| 104 latest_source_info_.set_invalid(); |
| 105 } |
| 106 } |
| 107 return source_position; |
| 91 } | 108 } |
| 92 | 109 |
| 93 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | 110 namespace { |
| 94 uint32_t operand1, uint32_t operand2) { | 111 |
| 95 DCHECK(OperandsAreValid(bytecode, 3, operand0, operand1, operand2)); | 112 template <OperandTypeInfo type_info> |
| 96 BytecodeNode node(bytecode, operand0, operand1, operand2, | 113 class UnsignedOperandHelper { |
| 97 &latest_source_info_); | 114 public: |
| 98 pipeline()->Write(&node); | 115 INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, size_t value)) { |
| 99 } | 116 DCHECK(IsValid(value)); |
| 100 | 117 return static_cast<uint32_t>(value); |
| 101 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | 118 } |
| 102 uint32_t operand1) { | 119 |
| 103 DCHECK(OperandsAreValid(bytecode, 2, operand0, operand1)); | 120 INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, int value)) { |
| 104 BytecodeNode node(bytecode, operand0, operand1, &latest_source_info_); | 121 DCHECK_GE(value, 0); |
| 105 pipeline()->Write(&node); | 122 return Convert(builder, static_cast<size_t>(value)); |
| 106 } | 123 } |
| 107 | 124 |
| 108 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0) { | 125 private: |
| 109 DCHECK(OperandsAreValid(bytecode, 1, operand0)); | 126 static bool IsValid(size_t value) { |
| 110 BytecodeNode node(bytecode, operand0, &latest_source_info_); | 127 switch (type_info) { |
| 111 pipeline()->Write(&node); | 128 case OperandTypeInfo::kFixedUnsignedByte: |
| 112 } | 129 return value <= kMaxUInt8; |
| 113 | 130 case OperandTypeInfo::kFixedUnsignedShort: |
| 114 void BytecodeArrayBuilder::Output(Bytecode bytecode) { | 131 return value <= kMaxUInt16; |
| 115 DCHECK(OperandsAreValid(bytecode, 0)); | 132 case OperandTypeInfo::kScalableUnsignedByte: |
| 116 BytecodeNode node(bytecode, &latest_source_info_); | 133 return value <= kMaxUInt32; |
| 117 pipeline()->Write(&node); | 134 default: |
| 118 } | 135 UNREACHABLE(); |
| 119 | 136 return false; |
| 120 void BytecodeArrayBuilder::OutputJump(Bytecode bytecode, BytecodeLabel* label) { | 137 } |
| 121 BytecodeNode node(bytecode, 0, &latest_source_info_); | 138 } |
| 122 pipeline_->WriteJump(&node, label); | 139 }; |
| 123 LeaveBasicBlock(); | 140 |
| 124 } | 141 template <OperandType> |
| 125 | 142 class OperandHelper {}; |
| 126 void BytecodeArrayBuilder::OutputJump(Bytecode bytecode, uint32_t operand0, | 143 |
| 127 BytecodeLabel* label) { | 144 #define DEFINE_UNSIGNED_OPERAND_HELPER(Name, Type) \ |
| 128 BytecodeNode node(bytecode, 0, operand0, &latest_source_info_); | 145 template <> \ |
| 129 pipeline_->WriteJump(&node, label); | 146 class OperandHelper<OperandType::k##Name> \ |
| 130 LeaveBasicBlock(); | 147 : public UnsignedOperandHelper<Type> {}; |
| 131 } | 148 UNSIGNED_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER) |
| 149 #undef DEFINE_UNSIGNED_OPERAND_HELPER |
| 150 |
| 151 template <> |
| 152 class OperandHelper<OperandType::kImm> { |
| 153 public: |
| 154 INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, int value)) { |
| 155 return static_cast<uint32_t>(value); |
| 156 } |
| 157 }; |
| 158 |
| 159 template <> |
| 160 class OperandHelper<OperandType::kReg> { |
| 161 public: |
| 162 INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, Register reg)) { |
| 163 return builder->GetInputRegisterOperand(reg); |
| 164 } |
| 165 }; |
| 166 |
| 167 template <> |
| 168 class OperandHelper<OperandType::kRegList> { |
| 169 public: |
| 170 INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, |
| 171 RegisterList reg_list)) { |
| 172 return builder->GetInputRegisterListOperand(reg_list); |
| 173 } |
| 174 }; |
| 175 |
| 176 template <> |
| 177 class OperandHelper<OperandType::kRegPair> { |
| 178 public: |
| 179 INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, |
| 180 RegisterList reg_list)) { |
| 181 DCHECK_EQ(reg_list.register_count(), 2); |
| 182 return builder->GetInputRegisterListOperand(reg_list); |
| 183 } |
| 184 }; |
| 185 |
| 186 template <> |
| 187 class OperandHelper<OperandType::kRegOut> { |
| 188 public: |
| 189 INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, Register reg)) { |
| 190 return builder->GetOutputRegisterOperand(reg); |
| 191 } |
| 192 }; |
| 193 |
| 194 template <> |
| 195 class OperandHelper<OperandType::kRegOutPair> { |
| 196 public: |
| 197 INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, |
| 198 RegisterList reg_list)) { |
| 199 DCHECK_EQ(2, reg_list.register_count()); |
| 200 return builder->GetOutputRegisterListOperand(reg_list); |
| 201 } |
| 202 }; |
| 203 |
| 204 template <> |
| 205 class OperandHelper<OperandType::kRegOutTriple> { |
| 206 public: |
| 207 INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, |
| 208 RegisterList reg_list)) { |
| 209 DCHECK_EQ(3, reg_list.register_count()); |
| 210 return builder->GetOutputRegisterListOperand(reg_list); |
| 211 } |
| 212 }; |
| 213 |
| 214 } // namespace |
| 215 |
| 216 template <OperandType... operand_types> |
| 217 class BytecodeNodeBuilder { |
| 218 public: |
| 219 template <typename... Operands> |
| 220 INLINE(static BytecodeNode Make(BytecodeArrayBuilder* builder, |
| 221 BytecodeSourceInfo source_info, |
| 222 Bytecode bytecode, Operands... operands)) { |
| 223 builder->PrepareToOutputBytecode(bytecode); |
| 224 // The "OperandHelper<operand_types>::Convert(builder, operands)..." will |
| 225 // expand both the OperandType... and Operands... parameter packs e.g. for: |
| 226 // BytecodeNodeBuilder<OperandType::kReg, OperandType::kImm>::Make< |
| 227 // Register, int>(..., Register reg, int immediate) |
| 228 // the code will expand into: |
| 229 // OperandHelper<OperandType::kReg>::Convert(builder, reg), |
| 230 // OperandHelper<OperandType::kImm>::Convert(builder, immediate), |
| 231 return BytecodeNode( |
| 232 bytecode, OperandHelper<operand_types>::Convert(builder, operands)..., |
| 233 source_info); |
| 234 } |
| 235 }; |
| 236 |
| 237 #define DEFINE_BYTECODE_OUTPUT(name, accumulator_use, ...) \ |
| 238 template <typename... Operands> \ |
| 239 void BytecodeArrayBuilder::Output##name(Operands... operands) { \ |
| 240 BytecodeNode node(BytecodeNodeBuilder<__VA_ARGS__>::Make<Operands...>( \ |
| 241 this, CurrentSourcePosition(Bytecode::k##name), Bytecode::k##name, \ |
| 242 operands...)); \ |
| 243 pipeline()->Write(&node); \ |
| 244 } \ |
| 245 \ |
| 246 template <typename... Operands> \ |
| 247 void BytecodeArrayBuilder::Output##name(BytecodeLabel* label, \ |
| 248 Operands... operands) { \ |
| 249 DCHECK(Bytecodes::IsJump(Bytecode::k##name)); \ |
| 250 BytecodeNode node(BytecodeNodeBuilder<__VA_ARGS__>::Make<Operands...>( \ |
| 251 this, CurrentSourcePosition(Bytecode::k##name), Bytecode::k##name, \ |
| 252 operands...)); \ |
| 253 pipeline()->WriteJump(&node, label); \ |
| 254 LeaveBasicBlock(); \ |
| 255 } |
| 256 BYTECODE_LIST(DEFINE_BYTECODE_OUTPUT) |
| 257 #undef DEFINE_BYTECODE_OUTPUT |
| 132 | 258 |
| 133 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, | 259 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, |
| 134 Register reg, | 260 Register reg, |
| 135 int feedback_slot) { | 261 int feedback_slot) { |
| 136 switch (op) { | 262 switch (op) { |
| 137 case Token::Value::ADD: | 263 case Token::Value::ADD: |
| 138 Output(Bytecode::kAdd, RegisterOperand(reg), | 264 OutputAdd(reg, feedback_slot); |
| 139 UnsignedOperand(feedback_slot)); | |
| 140 break; | 265 break; |
| 141 case Token::Value::SUB: | 266 case Token::Value::SUB: |
| 142 Output(Bytecode::kSub, RegisterOperand(reg), | 267 OutputSub(reg, feedback_slot); |
| 143 UnsignedOperand(feedback_slot)); | |
| 144 break; | 268 break; |
| 145 case Token::Value::MUL: | 269 case Token::Value::MUL: |
| 146 Output(Bytecode::kMul, RegisterOperand(reg), | 270 OutputMul(reg, feedback_slot); |
| 147 UnsignedOperand(feedback_slot)); | |
| 148 break; | 271 break; |
| 149 case Token::Value::DIV: | 272 case Token::Value::DIV: |
| 150 Output(Bytecode::kDiv, RegisterOperand(reg), | 273 OutputDiv(reg, feedback_slot); |
| 151 UnsignedOperand(feedback_slot)); | |
| 152 break; | 274 break; |
| 153 case Token::Value::MOD: | 275 case Token::Value::MOD: |
| 154 Output(Bytecode::kMod, RegisterOperand(reg), | 276 OutputMod(reg, feedback_slot); |
| 155 UnsignedOperand(feedback_slot)); | |
| 156 break; | 277 break; |
| 157 case Token::Value::BIT_OR: | 278 case Token::Value::BIT_OR: |
| 158 Output(Bytecode::kBitwiseOr, RegisterOperand(reg), | 279 OutputBitwiseOr(reg, feedback_slot); |
| 159 UnsignedOperand(feedback_slot)); | |
| 160 break; | 280 break; |
| 161 case Token::Value::BIT_XOR: | 281 case Token::Value::BIT_XOR: |
| 162 Output(Bytecode::kBitwiseXor, RegisterOperand(reg), | 282 OutputBitwiseXor(reg, feedback_slot); |
| 163 UnsignedOperand(feedback_slot)); | |
| 164 break; | 283 break; |
| 165 case Token::Value::BIT_AND: | 284 case Token::Value::BIT_AND: |
| 166 Output(Bytecode::kBitwiseAnd, RegisterOperand(reg), | 285 OutputBitwiseAnd(reg, feedback_slot); |
| 167 UnsignedOperand(feedback_slot)); | |
| 168 break; | 286 break; |
| 169 case Token::Value::SHL: | 287 case Token::Value::SHL: |
| 170 Output(Bytecode::kShiftLeft, RegisterOperand(reg), | 288 OutputShiftLeft(reg, feedback_slot); |
| 171 UnsignedOperand(feedback_slot)); | |
| 172 break; | 289 break; |
| 173 case Token::Value::SAR: | 290 case Token::Value::SAR: |
| 174 Output(Bytecode::kShiftRight, RegisterOperand(reg), | 291 OutputShiftRight(reg, feedback_slot); |
| 175 UnsignedOperand(feedback_slot)); | |
| 176 break; | 292 break; |
| 177 case Token::Value::SHR: | 293 case Token::Value::SHR: |
| 178 Output(Bytecode::kShiftRightLogical, RegisterOperand(reg), | 294 OutputShiftRightLogical(reg, feedback_slot); |
| 179 UnsignedOperand(feedback_slot)); | |
| 180 break; | 295 break; |
| 181 default: | 296 default: |
| 182 UNREACHABLE(); | 297 UNREACHABLE(); |
| 183 } | 298 } |
| 184 return *this; | 299 return *this; |
| 185 } | 300 } |
| 186 | 301 |
| 187 BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op, | 302 BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op, |
| 188 int feedback_slot) { | 303 int feedback_slot) { |
| 189 if (op == Token::Value::ADD) { | 304 if (op == Token::Value::ADD) { |
| 190 Output(Bytecode::kInc, UnsignedOperand(feedback_slot)); | 305 OutputInc(feedback_slot); |
| 191 } else { | 306 } else { |
| 192 DCHECK_EQ(op, Token::Value::SUB); | 307 DCHECK_EQ(op, Token::Value::SUB); |
| 193 Output(Bytecode::kDec, UnsignedOperand(feedback_slot)); | 308 OutputDec(feedback_slot); |
| 194 } | 309 } |
| 195 return *this; | 310 return *this; |
| 196 } | 311 } |
| 197 | 312 |
| 198 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() { | 313 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() { |
| 199 Output(Bytecode::kToBooleanLogicalNot); | 314 OutputToBooleanLogicalNot(); |
| 200 return *this; | 315 return *this; |
| 201 } | 316 } |
| 202 | 317 |
| 203 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() { | 318 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() { |
| 204 Output(Bytecode::kTypeOf); | 319 OutputTypeOf(); |
| 205 return *this; | 320 return *this; |
| 206 } | 321 } |
| 207 | 322 |
| 208 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation( | 323 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation( |
| 209 Token::Value op, Register reg, int feedback_slot) { | 324 Token::Value op, Register reg, int feedback_slot) { |
| 210 switch (op) { | 325 switch (op) { |
| 211 case Token::Value::EQ: | 326 case Token::Value::EQ: |
| 212 Output(Bytecode::kTestEqual, RegisterOperand(reg), | 327 OutputTestEqual(reg, feedback_slot); |
| 213 UnsignedOperand(feedback_slot)); | |
| 214 break; | 328 break; |
| 215 case Token::Value::NE: | 329 case Token::Value::NE: |
| 216 Output(Bytecode::kTestNotEqual, RegisterOperand(reg), | 330 OutputTestNotEqual(reg, feedback_slot); |
| 217 UnsignedOperand(feedback_slot)); | |
| 218 break; | 331 break; |
| 219 case Token::Value::EQ_STRICT: | 332 case Token::Value::EQ_STRICT: |
| 220 Output(Bytecode::kTestEqualStrict, RegisterOperand(reg), | 333 OutputTestEqualStrict(reg, feedback_slot); |
| 221 UnsignedOperand(feedback_slot)); | |
| 222 break; | 334 break; |
| 223 case Token::Value::LT: | 335 case Token::Value::LT: |
| 224 Output(Bytecode::kTestLessThan, RegisterOperand(reg), | 336 OutputTestLessThan(reg, feedback_slot); |
| 225 UnsignedOperand(feedback_slot)); | |
| 226 break; | 337 break; |
| 227 case Token::Value::GT: | 338 case Token::Value::GT: |
| 228 Output(Bytecode::kTestGreaterThan, RegisterOperand(reg), | 339 OutputTestGreaterThan(reg, feedback_slot); |
| 229 UnsignedOperand(feedback_slot)); | |
| 230 break; | 340 break; |
| 231 case Token::Value::LTE: | 341 case Token::Value::LTE: |
| 232 Output(Bytecode::kTestLessThanOrEqual, RegisterOperand(reg), | 342 OutputTestLessThanOrEqual(reg, feedback_slot); |
| 233 UnsignedOperand(feedback_slot)); | |
| 234 break; | 343 break; |
| 235 case Token::Value::GTE: | 344 case Token::Value::GTE: |
| 236 Output(Bytecode::kTestGreaterThanOrEqual, RegisterOperand(reg), | 345 OutputTestGreaterThanOrEqual(reg, feedback_slot); |
| 237 UnsignedOperand(feedback_slot)); | |
| 238 break; | 346 break; |
| 239 case Token::Value::INSTANCEOF: | 347 case Token::Value::INSTANCEOF: |
| 240 Output(Bytecode::kTestInstanceOf, RegisterOperand(reg)); | 348 OutputTestInstanceOf(reg); |
| 241 break; | 349 break; |
| 242 case Token::Value::IN: | 350 case Token::Value::IN: |
| 243 Output(Bytecode::kTestIn, RegisterOperand(reg)); | 351 OutputTestIn(reg); |
| 244 break; | 352 break; |
| 245 default: | 353 default: |
| 246 UNREACHABLE(); | 354 UNREACHABLE(); |
| 247 } | 355 } |
| 248 return *this; | 356 return *this; |
| 249 } | 357 } |
| 250 | 358 |
| 251 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry( | 359 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry( |
| 252 size_t entry) { | 360 size_t entry) { |
| 253 Output(Bytecode::kLdaConstant, UnsignedOperand(entry)); | 361 OutputLdaConstant(entry); |
| 254 return *this; | 362 return *this; |
| 255 } | 363 } |
| 256 | 364 |
| 257 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral( | 365 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral( |
| 258 v8::internal::Smi* smi) { | 366 v8::internal::Smi* smi) { |
| 259 int32_t raw_smi = smi->value(); | 367 int32_t raw_smi = smi->value(); |
| 260 if (raw_smi == 0) { | 368 if (raw_smi == 0) { |
| 261 Output(Bytecode::kLdaZero); | 369 OutputLdaZero(); |
| 262 } else { | 370 } else { |
| 263 Output(Bytecode::kLdaSmi, SignedOperand(raw_smi)); | 371 OutputLdaSmi(raw_smi); |
| 264 } | 372 } |
| 265 return *this; | 373 return *this; |
| 266 } | 374 } |
| 267 | 375 |
| 268 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) { | 376 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) { |
| 269 size_t entry = GetConstantPoolEntry(object); | 377 size_t entry = GetConstantPoolEntry(object); |
| 270 Output(Bytecode::kLdaConstant, UnsignedOperand(entry)); | 378 OutputLdaConstant(entry); |
| 271 return *this; | 379 return *this; |
| 272 } | 380 } |
| 273 | 381 |
| 274 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() { | 382 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() { |
| 275 Output(Bytecode::kLdaUndefined); | 383 OutputLdaUndefined(); |
| 276 return *this; | 384 return *this; |
| 277 } | 385 } |
| 278 | 386 |
| 279 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() { | 387 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() { |
| 280 Output(Bytecode::kLdaNull); | 388 OutputLdaNull(); |
| 281 return *this; | 389 return *this; |
| 282 } | 390 } |
| 283 | 391 |
| 284 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() { | 392 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() { |
| 285 Output(Bytecode::kLdaTheHole); | 393 OutputLdaTheHole(); |
| 286 return *this; | 394 return *this; |
| 287 } | 395 } |
| 288 | 396 |
| 289 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() { | 397 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() { |
| 290 Output(Bytecode::kLdaTrue); | 398 OutputLdaTrue(); |
| 291 return *this; | 399 return *this; |
| 292 } | 400 } |
| 293 | 401 |
| 294 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() { | 402 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() { |
| 295 Output(Bytecode::kLdaFalse); | 403 OutputLdaFalse(); |
| 296 return *this; | 404 return *this; |
| 297 } | 405 } |
| 298 | 406 |
| 299 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister( | 407 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister( |
| 300 Register reg) { | 408 Register reg) { |
| 301 Output(Bytecode::kLdar, RegisterOperand(reg)); | 409 if (register_optimizer_) { |
| 410 register_optimizer_->DoLdar(reg, CurrentSourcePosition(Bytecode::kLdar)); |
| 411 } else { |
| 412 OutputLdar(reg); |
| 413 } |
| 302 return *this; | 414 return *this; |
| 303 } | 415 } |
| 304 | 416 |
| 305 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister( | 417 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister( |
| 306 Register reg) { | 418 Register reg) { |
| 307 Output(Bytecode::kStar, RegisterOperand(reg)); | 419 if (register_optimizer_) { |
| 420 register_optimizer_->DoStar(reg, CurrentSourcePosition(Bytecode::kStar)); |
| 421 } else { |
| 422 OutputStar(reg); |
| 423 } |
| 308 return *this; | 424 return *this; |
| 309 } | 425 } |
| 310 | 426 |
| 311 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, | 427 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, |
| 312 Register to) { | 428 Register to) { |
| 313 DCHECK(from != to); | 429 DCHECK(from != to); |
| 314 Output(Bytecode::kMov, RegisterOperand(from), RegisterOperand(to)); | 430 if (register_optimizer_) { |
| 431 register_optimizer_->DoMov(from, to, CurrentSourcePosition(Bytecode::kMov)); |
| 432 } else { |
| 433 OutputMov(from, to); |
| 434 } |
| 315 return *this; | 435 return *this; |
| 316 } | 436 } |
| 317 | 437 |
| 318 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(int feedback_slot, | 438 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(int feedback_slot, |
| 319 TypeofMode typeof_mode) { | 439 TypeofMode typeof_mode) { |
| 320 if (typeof_mode == INSIDE_TYPEOF) { | 440 if (typeof_mode == INSIDE_TYPEOF) { |
| 321 Output(Bytecode::kLdaGlobalInsideTypeof, feedback_slot); | 441 OutputLdaGlobalInsideTypeof(feedback_slot); |
| 322 } else { | 442 } else { |
| 323 DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF); | 443 DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF); |
| 324 Output(Bytecode::kLdaGlobal, UnsignedOperand(feedback_slot)); | 444 OutputLdaGlobal(feedback_slot); |
| 325 } | 445 } |
| 326 return *this; | 446 return *this; |
| 327 } | 447 } |
| 328 | 448 |
| 329 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal( | 449 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal( |
| 330 const Handle<String> name, int feedback_slot, LanguageMode language_mode) { | 450 const Handle<String> name, int feedback_slot, LanguageMode language_mode) { |
| 331 size_t name_index = GetConstantPoolEntry(name); | 451 size_t name_index = GetConstantPoolEntry(name); |
| 332 if (language_mode == SLOPPY) { | 452 if (language_mode == SLOPPY) { |
| 333 Output(Bytecode::kStaGlobalSloppy, UnsignedOperand(name_index), | 453 OutputStaGlobalSloppy(name_index, feedback_slot); |
| 334 UnsignedOperand(feedback_slot)); | |
| 335 } else { | 454 } else { |
| 336 DCHECK_EQ(language_mode, STRICT); | 455 DCHECK_EQ(language_mode, STRICT); |
| 337 Output(Bytecode::kStaGlobalStrict, UnsignedOperand(name_index), | 456 OutputStaGlobalStrict(name_index, feedback_slot); |
| 338 UnsignedOperand(feedback_slot)); | |
| 339 } | 457 } |
| 340 return *this; | 458 return *this; |
| 341 } | 459 } |
| 342 | 460 |
| 343 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context, | 461 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context, |
| 344 int slot_index, | 462 int slot_index, |
| 345 int depth) { | 463 int depth) { |
| 346 Output(Bytecode::kLdaContextSlot, RegisterOperand(context), | 464 OutputLdaContextSlot(context, slot_index, depth); |
| 347 UnsignedOperand(slot_index), UnsignedOperand(depth)); | |
| 348 return *this; | 465 return *this; |
| 349 } | 466 } |
| 350 | 467 |
| 351 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context, | 468 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context, |
| 352 int slot_index, | 469 int slot_index, |
| 353 int depth) { | 470 int depth) { |
| 354 Output(Bytecode::kStaContextSlot, RegisterOperand(context), | 471 OutputStaContextSlot(context, slot_index, depth); |
| 355 UnsignedOperand(slot_index), UnsignedOperand(depth)); | |
| 356 return *this; | 472 return *this; |
| 357 } | 473 } |
| 358 | 474 |
| 359 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot( | 475 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot( |
| 360 const Handle<String> name, TypeofMode typeof_mode) { | 476 const Handle<String> name, TypeofMode typeof_mode) { |
| 361 size_t name_index = GetConstantPoolEntry(name); | 477 size_t name_index = GetConstantPoolEntry(name); |
| 362 if (typeof_mode == INSIDE_TYPEOF) { | 478 if (typeof_mode == INSIDE_TYPEOF) { |
| 363 Output(Bytecode::kLdaLookupSlotInsideTypeof, UnsignedOperand(name_index)); | 479 OutputLdaLookupSlotInsideTypeof(name_index); |
| 364 } else { | 480 } else { |
| 365 DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF); | 481 DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF); |
| 366 Output(Bytecode::kLdaLookupSlot, UnsignedOperand(name_index)); | 482 OutputLdaLookupSlot(name_index); |
| 367 } | 483 } |
| 368 return *this; | 484 return *this; |
| 369 } | 485 } |
| 370 | 486 |
| 371 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupContextSlot( | 487 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupContextSlot( |
| 372 const Handle<String> name, TypeofMode typeof_mode, int slot_index, | 488 const Handle<String> name, TypeofMode typeof_mode, int slot_index, |
| 373 int depth) { | 489 int depth) { |
| 374 Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF) | |
| 375 ? Bytecode::kLdaLookupContextSlotInsideTypeof | |
| 376 : Bytecode::kLdaLookupContextSlot; | |
| 377 size_t name_index = GetConstantPoolEntry(name); | 490 size_t name_index = GetConstantPoolEntry(name); |
| 378 Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(slot_index), | 491 if (typeof_mode == INSIDE_TYPEOF) { |
| 379 UnsignedOperand(depth)); | 492 OutputLdaLookupContextSlotInsideTypeof(name_index, slot_index, depth); |
| 493 } else { |
| 494 DCHECK(typeof_mode == NOT_INSIDE_TYPEOF); |
| 495 OutputLdaLookupContextSlot(name_index, slot_index, depth); |
| 496 } |
| 380 return *this; | 497 return *this; |
| 381 } | 498 } |
| 382 | 499 |
| 383 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupGlobalSlot( | 500 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupGlobalSlot( |
| 384 const Handle<String> name, TypeofMode typeof_mode, int feedback_slot, | 501 const Handle<String> name, TypeofMode typeof_mode, int feedback_slot, |
| 385 int depth) { | 502 int depth) { |
| 386 Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF) | |
| 387 ? Bytecode::kLdaLookupGlobalSlotInsideTypeof | |
| 388 : Bytecode::kLdaLookupGlobalSlot; | |
| 389 size_t name_index = GetConstantPoolEntry(name); | 503 size_t name_index = GetConstantPoolEntry(name); |
| 390 Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(feedback_slot), | 504 if (typeof_mode == INSIDE_TYPEOF) { |
| 391 UnsignedOperand(depth)); | 505 OutputLdaLookupGlobalSlotInsideTypeof(name_index, feedback_slot, depth); |
| 506 } else { |
| 507 DCHECK(typeof_mode == NOT_INSIDE_TYPEOF); |
| 508 OutputLdaLookupGlobalSlot(name_index, feedback_slot, depth); |
| 509 } |
| 392 return *this; | 510 return *this; |
| 393 } | 511 } |
| 394 | 512 |
| 395 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot( | 513 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot( |
| 396 const Handle<String> name, LanguageMode language_mode) { | 514 const Handle<String> name, LanguageMode language_mode) { |
| 397 size_t name_index = GetConstantPoolEntry(name); | 515 size_t name_index = GetConstantPoolEntry(name); |
| 398 if (language_mode == SLOPPY) { | 516 if (language_mode == SLOPPY) { |
| 399 Output(Bytecode::kStaLookupSlotSloppy, UnsignedOperand(name_index)); | 517 OutputStaLookupSlotSloppy(name_index); |
| 400 } else { | 518 } else { |
| 401 DCHECK_EQ(language_mode, STRICT); | 519 DCHECK_EQ(language_mode, STRICT); |
| 402 Output(Bytecode::kStaLookupSlotStrict, UnsignedOperand(name_index)); | 520 OutputStaLookupSlotStrict(name_index); |
| 403 } | 521 } |
| 404 return *this; | 522 return *this; |
| 405 } | 523 } |
| 406 | 524 |
| 407 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( | 525 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( |
| 408 Register object, const Handle<Name> name, int feedback_slot) { | 526 Register object, const Handle<Name> name, int feedback_slot) { |
| 409 size_t name_index = GetConstantPoolEntry(name); | 527 size_t name_index = GetConstantPoolEntry(name); |
| 410 Output(Bytecode::kLdaNamedProperty, RegisterOperand(object), | 528 OutputLdaNamedProperty(object, name_index, feedback_slot); |
| 411 UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); | |
| 412 return *this; | 529 return *this; |
| 413 } | 530 } |
| 414 | 531 |
| 415 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( | 532 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( |
| 416 Register object, int feedback_slot) { | 533 Register object, int feedback_slot) { |
| 417 Output(Bytecode::kLdaKeyedProperty, RegisterOperand(object), | 534 OutputLdaKeyedProperty(object, feedback_slot); |
| 418 UnsignedOperand(feedback_slot)); | |
| 419 return *this; | 535 return *this; |
| 420 } | 536 } |
| 421 | 537 |
| 422 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( | 538 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( |
| 423 Register object, const Handle<Name> name, int feedback_slot, | 539 Register object, const Handle<Name> name, int feedback_slot, |
| 424 LanguageMode language_mode) { | 540 LanguageMode language_mode) { |
| 425 size_t name_index = GetConstantPoolEntry(name); | 541 size_t name_index = GetConstantPoolEntry(name); |
| 426 if (language_mode == SLOPPY) { | 542 if (language_mode == SLOPPY) { |
| 427 Output(Bytecode::kStaNamedPropertySloppy, RegisterOperand(object), | 543 OutputStaNamedPropertySloppy(object, name_index, feedback_slot); |
| 428 UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); | |
| 429 } else { | 544 } else { |
| 430 DCHECK_EQ(language_mode, STRICT); | 545 DCHECK_EQ(language_mode, STRICT); |
| 431 Output(Bytecode::kStaNamedPropertyStrict, RegisterOperand(object), | 546 OutputStaNamedPropertyStrict(object, name_index, feedback_slot); |
| 432 UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); | |
| 433 } | 547 } |
| 434 return *this; | 548 return *this; |
| 435 } | 549 } |
| 436 | 550 |
| 437 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( | 551 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( |
| 438 Register object, Register key, int feedback_slot, | 552 Register object, Register key, int feedback_slot, |
| 439 LanguageMode language_mode) { | 553 LanguageMode language_mode) { |
| 440 if (language_mode == SLOPPY) { | 554 if (language_mode == SLOPPY) { |
| 441 Output(Bytecode::kStaKeyedPropertySloppy, RegisterOperand(object), | 555 OutputStaKeyedPropertySloppy(object, key, feedback_slot); |
| 442 RegisterOperand(key), UnsignedOperand(feedback_slot)); | |
| 443 } else { | 556 } else { |
| 444 DCHECK_EQ(language_mode, STRICT); | 557 DCHECK_EQ(language_mode, STRICT); |
| 445 Output(Bytecode::kStaKeyedPropertyStrict, RegisterOperand(object), | 558 OutputStaKeyedPropertyStrict(object, key, feedback_slot); |
| 446 RegisterOperand(key), UnsignedOperand(feedback_slot)); | |
| 447 } | 559 } |
| 448 return *this; | 560 return *this; |
| 449 } | 561 } |
| 450 | 562 |
| 451 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(size_t entry, | 563 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(size_t entry, |
| 452 int flags) { | 564 int flags) { |
| 453 Output(Bytecode::kCreateClosure, UnsignedOperand(entry), | 565 OutputCreateClosure(entry, flags); |
| 454 UnsignedOperand(flags)); | |
| 455 return *this; | 566 return *this; |
| 456 } | 567 } |
| 457 | 568 |
| 458 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateBlockContext( | 569 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateBlockContext( |
| 459 Handle<ScopeInfo> scope_info) { | 570 Handle<ScopeInfo> scope_info) { |
| 460 size_t entry = GetConstantPoolEntry(scope_info); | 571 size_t entry = GetConstantPoolEntry(scope_info); |
| 461 Output(Bytecode::kCreateBlockContext, UnsignedOperand(entry)); | 572 OutputCreateBlockContext(entry); |
| 462 return *this; | 573 return *this; |
| 463 } | 574 } |
| 464 | 575 |
| 465 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateCatchContext( | 576 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateCatchContext( |
| 466 Register exception, Handle<String> name, Handle<ScopeInfo> scope_info) { | 577 Register exception, Handle<String> name, Handle<ScopeInfo> scope_info) { |
| 467 size_t name_index = GetConstantPoolEntry(name); | 578 size_t name_index = GetConstantPoolEntry(name); |
| 468 size_t scope_info_index = GetConstantPoolEntry(scope_info); | 579 size_t scope_info_index = GetConstantPoolEntry(scope_info); |
| 469 Output(Bytecode::kCreateCatchContext, RegisterOperand(exception), | 580 OutputCreateCatchContext(exception, name_index, scope_info_index); |
| 470 UnsignedOperand(name_index), UnsignedOperand(scope_info_index)); | |
| 471 return *this; | 581 return *this; |
| 472 } | 582 } |
| 473 | 583 |
| 474 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateFunctionContext(int slots) { | 584 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateFunctionContext(int slots) { |
| 475 Output(Bytecode::kCreateFunctionContext, UnsignedOperand(slots)); | 585 OutputCreateFunctionContext(slots); |
| 476 return *this; | 586 return *this; |
| 477 } | 587 } |
| 478 | 588 |
| 479 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext( | 589 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext( |
| 480 Register object, Handle<ScopeInfo> scope_info) { | 590 Register object, Handle<ScopeInfo> scope_info) { |
| 481 size_t scope_info_index = GetConstantPoolEntry(scope_info); | 591 size_t scope_info_index = GetConstantPoolEntry(scope_info); |
| 482 Output(Bytecode::kCreateWithContext, RegisterOperand(object), | 592 OutputCreateWithContext(object, scope_info_index); |
| 483 UnsignedOperand(scope_info_index)); | |
| 484 return *this; | 593 return *this; |
| 485 } | 594 } |
| 486 | 595 |
| 487 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments( | 596 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments( |
| 488 CreateArgumentsType type) { | 597 CreateArgumentsType type) { |
| 489 switch (type) { | 598 switch (type) { |
| 490 case CreateArgumentsType::kMappedArguments: | 599 case CreateArgumentsType::kMappedArguments: |
| 491 Output(Bytecode::kCreateMappedArguments); | 600 OutputCreateMappedArguments(); |
| 492 break; | 601 break; |
| 493 case CreateArgumentsType::kUnmappedArguments: | 602 case CreateArgumentsType::kUnmappedArguments: |
| 494 Output(Bytecode::kCreateUnmappedArguments); | 603 OutputCreateUnmappedArguments(); |
| 495 break; | 604 break; |
| 496 case CreateArgumentsType::kRestParameter: | 605 case CreateArgumentsType::kRestParameter: |
| 497 Output(Bytecode::kCreateRestParameter); | 606 OutputCreateRestParameter(); |
| 498 break; | 607 break; |
| 499 default: | 608 default: |
| 500 UNREACHABLE(); | 609 UNREACHABLE(); |
| 501 } | 610 } |
| 502 return *this; | 611 return *this; |
| 503 } | 612 } |
| 504 | 613 |
| 505 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral( | 614 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral( |
| 506 Handle<String> pattern, int literal_index, int flags) { | 615 Handle<String> pattern, int literal_index, int flags) { |
| 507 size_t pattern_entry = GetConstantPoolEntry(pattern); | 616 size_t pattern_entry = GetConstantPoolEntry(pattern); |
| 508 Output(Bytecode::kCreateRegExpLiteral, UnsignedOperand(pattern_entry), | 617 OutputCreateRegExpLiteral(pattern_entry, literal_index, flags); |
| 509 UnsignedOperand(literal_index), UnsignedOperand(flags)); | |
| 510 return *this; | 618 return *this; |
| 511 } | 619 } |
| 512 | 620 |
| 513 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral( | 621 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral( |
| 514 Handle<FixedArray> constant_elements, int literal_index, int flags) { | 622 Handle<FixedArray> constant_elements, int literal_index, int flags) { |
| 515 size_t constant_elements_entry = GetConstantPoolEntry(constant_elements); | 623 size_t constant_elements_entry = GetConstantPoolEntry(constant_elements); |
| 516 Output(Bytecode::kCreateArrayLiteral, | 624 OutputCreateArrayLiteral(constant_elements_entry, literal_index, flags); |
| 517 UnsignedOperand(constant_elements_entry), | |
| 518 UnsignedOperand(literal_index), UnsignedOperand(flags)); | |
| 519 return *this; | 625 return *this; |
| 520 } | 626 } |
| 521 | 627 |
| 522 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral( | 628 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral( |
| 523 Handle<FixedArray> constant_properties, int literal_index, int flags, | 629 Handle<FixedArray> constant_properties, int literal_index, int flags, |
| 524 Register output) { | 630 Register output) { |
| 525 size_t constant_properties_entry = GetConstantPoolEntry(constant_properties); | 631 size_t constant_properties_entry = GetConstantPoolEntry(constant_properties); |
| 526 Output(Bytecode::kCreateObjectLiteral, | 632 OutputCreateObjectLiteral(constant_properties_entry, literal_index, flags, |
| 527 UnsignedOperand(constant_properties_entry), | 633 output); |
| 528 UnsignedOperand(literal_index), UnsignedOperand(flags), | |
| 529 RegisterOperand(output)); | |
| 530 return *this; | 634 return *this; |
| 531 } | 635 } |
| 532 | 636 |
| 533 BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) { | 637 BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) { |
| 534 Output(Bytecode::kPushContext, RegisterOperand(context)); | 638 OutputPushContext(context); |
| 535 return *this; | 639 return *this; |
| 536 } | 640 } |
| 537 | 641 |
| 538 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) { | 642 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) { |
| 539 Output(Bytecode::kPopContext, RegisterOperand(context)); | 643 OutputPopContext(context); |
| 540 return *this; | 644 return *this; |
| 541 } | 645 } |
| 542 | 646 |
| 543 BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToObject( | 647 BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToObject( |
| 544 Register out) { | 648 Register out) { |
| 545 Output(Bytecode::kToObject, RegisterOperand(out)); | 649 OutputToObject(out); |
| 546 return *this; | 650 return *this; |
| 547 } | 651 } |
| 548 | 652 |
| 549 BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToName( | 653 BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToName( |
| 550 Register out) { | 654 Register out) { |
| 551 Output(Bytecode::kToName, RegisterOperand(out)); | 655 OutputToName(out); |
| 552 return *this; | 656 return *this; |
| 553 } | 657 } |
| 554 | 658 |
| 555 BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToNumber( | 659 BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToNumber( |
| 556 Register out) { | 660 Register out) { |
| 557 Output(Bytecode::kToNumber, RegisterOperand(out)); | 661 OutputToNumber(out); |
| 558 return *this; | 662 return *this; |
| 559 } | 663 } |
| 560 | 664 |
| 561 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) { | 665 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) { |
| 666 // Flush the register optimizer when binding a label to ensure all |
| 667 // expected registers are valid when jumping to this label. |
| 668 if (register_optimizer_) register_optimizer_->Flush(); |
| 562 pipeline_->BindLabel(label); | 669 pipeline_->BindLabel(label); |
| 563 LeaveBasicBlock(); | 670 LeaveBasicBlock(); |
| 564 return *this; | 671 return *this; |
| 565 } | 672 } |
| 566 | 673 |
| 567 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target, | 674 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target, |
| 568 BytecodeLabel* label) { | 675 BytecodeLabel* label) { |
| 569 pipeline_->BindLabel(target, label); | 676 pipeline_->BindLabel(target, label); |
| 570 LeaveBasicBlock(); | 677 LeaveBasicBlock(); |
| 571 return *this; | 678 return *this; |
| 572 } | 679 } |
| 573 | 680 |
| 574 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { | 681 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { |
| 575 OutputJump(Bytecode::kJump, label); | 682 OutputJump(label, 0); |
| 576 return *this; | 683 return *this; |
| 577 } | 684 } |
| 578 | 685 |
| 579 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) { | 686 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) { |
| 580 // The peephole optimizer attempts to simplify JumpIfToBooleanTrue | 687 // The peephole optimizer attempts to simplify JumpIfToBooleanTrue |
| 581 // to JumpIfTrue. | 688 // to JumpIfTrue. |
| 582 OutputJump(Bytecode::kJumpIfToBooleanTrue, label); | 689 OutputJumpIfToBooleanTrue(label, 0); |
| 583 return *this; | 690 return *this; |
| 584 } | 691 } |
| 585 | 692 |
| 586 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) { | 693 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) { |
| 587 OutputJump(Bytecode::kJumpIfToBooleanFalse, label); | 694 OutputJumpIfToBooleanFalse(label, 0); |
| 588 return *this; | 695 return *this; |
| 589 } | 696 } |
| 590 | 697 |
| 591 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) { | 698 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) { |
| 592 OutputJump(Bytecode::kJumpIfNull, label); | 699 OutputJumpIfNull(label, 0); |
| 593 return *this; | 700 return *this; |
| 594 } | 701 } |
| 595 | 702 |
| 596 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined( | 703 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined( |
| 597 BytecodeLabel* label) { | 704 BytecodeLabel* label) { |
| 598 OutputJump(Bytecode::kJumpIfUndefined, label); | 705 OutputJumpIfUndefined(label, 0); |
| 599 return *this; | 706 return *this; |
| 600 } | 707 } |
| 601 | 708 |
| 602 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole( | 709 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole( |
| 603 BytecodeLabel* label) { | 710 BytecodeLabel* label) { |
| 604 OutputJump(Bytecode::kJumpIfNotHole, label); | 711 OutputJumpIfNotHole(label, 0); |
| 605 return *this; | 712 return *this; |
| 606 } | 713 } |
| 607 | 714 |
| 608 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label, | 715 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label, |
| 609 int loop_depth) { | 716 int loop_depth) { |
| 610 OutputJump(Bytecode::kJumpLoop, UnsignedOperand(loop_depth), label); | 717 OutputJumpLoop(label, 0, loop_depth); |
| 611 return *this; | 718 return *this; |
| 612 } | 719 } |
| 613 | 720 |
| 614 BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) { | 721 BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) { |
| 615 if (position != kNoSourcePosition) { | 722 if (position != kNoSourcePosition) { |
| 616 // We need to attach a non-breakable source position to a stack | 723 // We need to attach a non-breakable source position to a stack |
| 617 // check, so we simply add it as expression position. There can be | 724 // check, so we simply add it as expression position. There can be |
| 618 // a prior statement position from constructs like: | 725 // a prior statement position from constructs like: |
| 619 // | 726 // |
| 620 // do var x; while (false); | 727 // do var x; while (false); |
| 621 // | 728 // |
| 622 // A Nop could be inserted for empty statements, but since no code | 729 // A Nop could be inserted for empty statements, but since no code |
| 623 // is associated with these positions, instead we force the stack | 730 // is associated with these positions, instead we force the stack |
| 624 // check's expression position which eliminates the empty | 731 // check's expression position which eliminates the empty |
| 625 // statement's position. | 732 // statement's position. |
| 626 latest_source_info_.ForceExpressionPosition(position); | 733 latest_source_info_.ForceExpressionPosition(position); |
| 627 } | 734 } |
| 628 Output(Bytecode::kStackCheck); | 735 OutputStackCheck(); |
| 629 return *this; | 736 return *this; |
| 630 } | 737 } |
| 631 | 738 |
| 632 BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() { | 739 BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() { |
| 633 Output(Bytecode::kThrow); | 740 OutputThrow(); |
| 634 return *this; | 741 return *this; |
| 635 } | 742 } |
| 636 | 743 |
| 637 BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() { | 744 BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() { |
| 638 Output(Bytecode::kReThrow); | 745 OutputReThrow(); |
| 639 return *this; | 746 return *this; |
| 640 } | 747 } |
| 641 | 748 |
| 642 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() { | 749 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() { |
| 643 SetReturnPosition(); | 750 SetReturnPosition(); |
| 644 Output(Bytecode::kReturn); | 751 OutputReturn(); |
| 645 return_seen_in_block_ = true; | 752 return_seen_in_block_ = true; |
| 646 return *this; | 753 return *this; |
| 647 } | 754 } |
| 648 | 755 |
| 649 BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() { | 756 BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() { |
| 650 Output(Bytecode::kDebugger); | 757 OutputDebugger(); |
| 651 return *this; | 758 return *this; |
| 652 } | 759 } |
| 653 | 760 |
| 654 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare( | 761 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare( |
| 655 Register receiver, RegisterList cache_info_triple) { | 762 Register receiver, RegisterList cache_info_triple) { |
| 656 DCHECK_EQ(3, cache_info_triple.register_count()); | 763 DCHECK_EQ(3, cache_info_triple.register_count()); |
| 657 Output(Bytecode::kForInPrepare, RegisterOperand(receiver), | 764 OutputForInPrepare(receiver, cache_info_triple); |
| 658 RegisterOperand(cache_info_triple.first_register())); | |
| 659 return *this; | 765 return *this; |
| 660 } | 766 } |
| 661 | 767 |
| 662 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInContinue( | 768 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInContinue( |
| 663 Register index, Register cache_length) { | 769 Register index, Register cache_length) { |
| 664 Output(Bytecode::kForInContinue, RegisterOperand(index), | 770 OutputForInContinue(index, cache_length); |
| 665 RegisterOperand(cache_length)); | |
| 666 return *this; | 771 return *this; |
| 667 } | 772 } |
| 668 | 773 |
| 669 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext( | 774 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext( |
| 670 Register receiver, Register index, RegisterList cache_type_array_pair, | 775 Register receiver, Register index, RegisterList cache_type_array_pair, |
| 671 int feedback_slot) { | 776 int feedback_slot) { |
| 672 DCHECK_EQ(2, cache_type_array_pair.register_count()); | 777 DCHECK_EQ(2, cache_type_array_pair.register_count()); |
| 673 Output(Bytecode::kForInNext, RegisterOperand(receiver), | 778 OutputForInNext(receiver, index, cache_type_array_pair, feedback_slot); |
| 674 RegisterOperand(index), | |
| 675 RegisterOperand(cache_type_array_pair.first_register()), | |
| 676 UnsignedOperand(feedback_slot)); | |
| 677 return *this; | 779 return *this; |
| 678 } | 780 } |
| 679 | 781 |
| 680 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) { | 782 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) { |
| 681 Output(Bytecode::kForInStep, RegisterOperand(index)); | 783 OutputForInStep(index); |
| 682 return *this; | 784 return *this; |
| 683 } | 785 } |
| 684 | 786 |
| 685 BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator( | 787 BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator( |
| 686 Register generator) { | 788 Register generator) { |
| 687 Output(Bytecode::kSuspendGenerator, RegisterOperand(generator)); | 789 OutputSuspendGenerator(generator); |
| 688 return *this; | 790 return *this; |
| 689 } | 791 } |
| 690 | 792 |
| 691 BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator( | 793 BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator( |
| 692 Register generator) { | 794 Register generator) { |
| 693 Output(Bytecode::kResumeGenerator, RegisterOperand(generator)); | 795 OutputResumeGenerator(generator); |
| 694 return *this; | 796 return *this; |
| 695 } | 797 } |
| 696 | 798 |
| 697 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler( | 799 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler( |
| 698 int handler_id, HandlerTable::CatchPrediction catch_prediction) { | 800 int handler_id, HandlerTable::CatchPrediction catch_prediction) { |
| 699 BytecodeLabel handler; | 801 BytecodeLabel handler; |
| 700 Bind(&handler); | 802 Bind(&handler); |
| 701 handler_table_builder()->SetHandlerTarget(handler_id, handler.offset()); | 803 handler_table_builder()->SetHandlerTarget(handler_id, handler.offset()); |
| 702 handler_table_builder()->SetPrediction(handler_id, catch_prediction); | 804 handler_table_builder()->SetPrediction(handler_id, catch_prediction); |
| 703 return *this; | 805 return *this; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 717 Bind(&try_end); | 819 Bind(&try_end); |
| 718 handler_table_builder()->SetTryRegionEnd(handler_id, try_end.offset()); | 820 handler_table_builder()->SetTryRegionEnd(handler_id, try_end.offset()); |
| 719 return *this; | 821 return *this; |
| 720 } | 822 } |
| 721 | 823 |
| 722 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, | 824 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, |
| 723 RegisterList args, | 825 RegisterList args, |
| 724 int feedback_slot, | 826 int feedback_slot, |
| 725 TailCallMode tail_call_mode) { | 827 TailCallMode tail_call_mode) { |
| 726 if (tail_call_mode == TailCallMode::kDisallow) { | 828 if (tail_call_mode == TailCallMode::kDisallow) { |
| 727 Output(Bytecode::kCall, RegisterOperand(callable), | 829 OutputCall(callable, args, args.register_count(), feedback_slot); |
| 728 RegisterOperand(args.first_register()), | |
| 729 UnsignedOperand(args.register_count()), | |
| 730 UnsignedOperand(feedback_slot)); | |
| 731 } else { | 830 } else { |
| 732 DCHECK(tail_call_mode == TailCallMode::kAllow); | 831 DCHECK(tail_call_mode == TailCallMode::kAllow); |
| 733 Output(Bytecode::kTailCall, RegisterOperand(callable), | 832 OutputTailCall(callable, args, args.register_count(), feedback_slot); |
| 734 RegisterOperand(args.first_register()), | |
| 735 UnsignedOperand(args.register_count()), | |
| 736 UnsignedOperand(feedback_slot)); | |
| 737 } | 833 } |
| 738 return *this; | 834 return *this; |
| 739 } | 835 } |
| 740 | 836 |
| 741 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, | 837 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, |
| 742 RegisterList args, | 838 RegisterList args, |
| 743 int feedback_slot_id) { | 839 int feedback_slot_id) { |
| 744 Output(Bytecode::kNew, RegisterOperand(constructor), | 840 OutputNew(constructor, args, args.register_count(), feedback_slot_id); |
| 745 RegisterOperand(args.first_register()), | |
| 746 UnsignedOperand(args.register_count()), | |
| 747 UnsignedOperand(feedback_slot_id)); | |
| 748 return *this; | 841 return *this; |
| 749 } | 842 } |
| 750 | 843 |
| 751 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( | 844 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( |
| 752 Runtime::FunctionId function_id, RegisterList args) { | 845 Runtime::FunctionId function_id, RegisterList args) { |
| 753 DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size); | 846 DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size); |
| 754 DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort); | 847 DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort); |
| 755 Bytecode bytecode; | |
| 756 uint32_t id; | |
| 757 if (IntrinsicsHelper::IsSupported(function_id)) { | 848 if (IntrinsicsHelper::IsSupported(function_id)) { |
| 758 bytecode = Bytecode::kInvokeIntrinsic; | 849 IntrinsicsHelper::IntrinsicId intrinsic_id = |
| 759 id = static_cast<uint32_t>(IntrinsicsHelper::FromRuntimeId(function_id)); | 850 IntrinsicsHelper::FromRuntimeId(function_id); |
| 851 OutputInvokeIntrinsic(static_cast<int>(intrinsic_id), args, |
| 852 args.register_count()); |
| 760 } else { | 853 } else { |
| 761 bytecode = Bytecode::kCallRuntime; | 854 OutputCallRuntime(static_cast<int>(function_id), args, |
| 762 id = static_cast<uint32_t>(function_id); | 855 args.register_count()); |
| 763 } | 856 } |
| 764 Output(bytecode, id, RegisterOperand(args.first_register()), | |
| 765 UnsignedOperand(args.register_count())); | |
| 766 return *this; | 857 return *this; |
| 767 } | 858 } |
| 768 | 859 |
| 769 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( | 860 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( |
| 770 Runtime::FunctionId function_id, Register arg) { | 861 Runtime::FunctionId function_id, Register arg) { |
| 771 return CallRuntime(function_id, RegisterList(arg.index(), 1)); | 862 return CallRuntime(function_id, RegisterList(arg.index(), 1)); |
| 772 } | 863 } |
| 773 | 864 |
| 774 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( | 865 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( |
| 775 Runtime::FunctionId function_id) { | 866 Runtime::FunctionId function_id) { |
| 776 return CallRuntime(function_id, RegisterList()); | 867 return CallRuntime(function_id, RegisterList()); |
| 777 } | 868 } |
| 778 | 869 |
| 779 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair( | 870 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair( |
| 780 Runtime::FunctionId function_id, RegisterList args, | 871 Runtime::FunctionId function_id, RegisterList args, |
| 781 RegisterList return_pair) { | 872 RegisterList return_pair) { |
| 782 DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size); | 873 DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size); |
| 783 DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort); | 874 DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort); |
| 784 DCHECK_EQ(2, return_pair.register_count()); | 875 DCHECK_EQ(2, return_pair.register_count()); |
| 785 Output(Bytecode::kCallRuntimeForPair, static_cast<uint16_t>(function_id), | 876 OutputCallRuntimeForPair(static_cast<uint16_t>(function_id), args, |
| 786 RegisterOperand(args.first_register()), | 877 args.register_count(), return_pair); |
| 787 UnsignedOperand(args.register_count()), | |
| 788 RegisterOperand(return_pair.first_register())); | |
| 789 return *this; | 878 return *this; |
| 790 } | 879 } |
| 791 | 880 |
| 792 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair( | 881 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair( |
| 793 Runtime::FunctionId function_id, Register arg, RegisterList return_pair) { | 882 Runtime::FunctionId function_id, Register arg, RegisterList return_pair) { |
| 794 return CallRuntimeForPair(function_id, RegisterList(arg.index(), 1), | 883 return CallRuntimeForPair(function_id, RegisterList(arg.index(), 1), |
| 795 return_pair); | 884 return_pair); |
| 796 } | 885 } |
| 797 | 886 |
| 798 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index, | 887 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index, |
| 799 RegisterList args) { | 888 RegisterList args) { |
| 800 Output(Bytecode::kCallJSRuntime, UnsignedOperand(context_index), | 889 OutputCallJSRuntime(context_index, args, args.register_count()); |
| 801 RegisterOperand(args.first_register()), | |
| 802 UnsignedOperand(args.register_count())); | |
| 803 return *this; | 890 return *this; |
| 804 } | 891 } |
| 805 | 892 |
| 806 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, | 893 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, |
| 807 LanguageMode language_mode) { | 894 LanguageMode language_mode) { |
| 808 if (language_mode == SLOPPY) { | 895 if (language_mode == SLOPPY) { |
| 809 Output(Bytecode::kDeletePropertySloppy, RegisterOperand(object)); | 896 OutputDeletePropertySloppy(object); |
| 810 } else { | 897 } else { |
| 811 DCHECK_EQ(language_mode, STRICT); | 898 DCHECK_EQ(language_mode, STRICT); |
| 812 Output(Bytecode::kDeletePropertyStrict, RegisterOperand(object)); | 899 OutputDeletePropertyStrict(object); |
| 813 } | 900 } |
| 814 return *this; | 901 return *this; |
| 815 } | 902 } |
| 816 | 903 |
| 817 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { | 904 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { |
| 818 return constant_array_builder()->Insert(object); | 905 return constant_array_builder()->Insert(object); |
| 819 } | 906 } |
| 820 | 907 |
| 821 size_t BytecodeArrayBuilder::AllocateConstantPoolEntry() { | 908 size_t BytecodeArrayBuilder::AllocateConstantPoolEntry() { |
| 822 return constant_array_builder()->AllocateEntry(); | 909 return constant_array_builder()->AllocateEntry(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 843 } else if (reg.is_parameter()) { | 930 } else if (reg.is_parameter()) { |
| 844 int parameter_index = reg.ToParameterIndex(parameter_count()); | 931 int parameter_index = reg.ToParameterIndex(parameter_count()); |
| 845 return parameter_index >= 0 && parameter_index < parameter_count(); | 932 return parameter_index >= 0 && parameter_index < parameter_count(); |
| 846 } else if (reg.index() < fixed_register_count()) { | 933 } else if (reg.index() < fixed_register_count()) { |
| 847 return true; | 934 return true; |
| 848 } else { | 935 } else { |
| 849 return register_allocator()->RegisterIsLive(reg); | 936 return register_allocator()->RegisterIsLive(reg); |
| 850 } | 937 } |
| 851 } | 938 } |
| 852 | 939 |
| 853 bool BytecodeArrayBuilder::OperandsAreValid( | 940 bool BytecodeArrayBuilder::RegisterListIsValid(RegisterList reg_list) const { |
| 854 Bytecode bytecode, int operand_count, uint32_t operand0, uint32_t operand1, | 941 if (reg_list.register_count() == 0) { |
| 855 uint32_t operand2, uint32_t operand3) const { | 942 return reg_list.first_register() == Register(0); |
| 856 if (Bytecodes::NumberOfOperands(bytecode) != operand_count) { | 943 } else { |
| 857 return false; | 944 int first_reg_index = reg_list.first_register().index(); |
| 945 for (int i = 0; i < reg_list.register_count(); i++) { |
| 946 if (!RegisterIsValid(Register(first_reg_index + i))) { |
| 947 return false; |
| 948 } |
| 949 } |
| 950 return true; |
| 858 } | 951 } |
| 952 } |
| 859 | 953 |
| 860 uint32_t operands[] = {operand0, operand1, operand2, operand3}; | 954 void BytecodeArrayBuilder::PrepareToOutputBytecode(Bytecode bytecode) { |
| 861 const OperandType* operand_types = Bytecodes::GetOperandTypes(bytecode); | 955 if (register_optimizer_) register_optimizer_->PrepareForBytecode(bytecode); |
| 862 for (int i = 0; i < operand_count; ++i) { | 956 } |
| 863 switch (operand_types[i]) { | |
| 864 case OperandType::kNone: | |
| 865 return false; | |
| 866 case OperandType::kFlag8: | |
| 867 case OperandType::kIntrinsicId: | |
| 868 if (Bytecodes::SizeForUnsignedOperand(operands[i]) > | |
| 869 OperandSize::kByte) { | |
| 870 return false; | |
| 871 } | |
| 872 break; | |
| 873 case OperandType::kRuntimeId: | |
| 874 if (Bytecodes::SizeForUnsignedOperand(operands[i]) > | |
| 875 OperandSize::kShort) { | |
| 876 return false; | |
| 877 } | |
| 878 break; | |
| 879 case OperandType::kIdx: | |
| 880 // TODO(leszeks): Possibly split this up into constant pool indices and | |
| 881 // other indices, for checking. | |
| 882 break; | |
| 883 case OperandType::kUImm: | |
| 884 case OperandType::kImm: | |
| 885 break; | |
| 886 case OperandType::kRegList: { | |
| 887 CHECK_LT(i, operand_count - 1); | |
| 888 CHECK(operand_types[i + 1] == OperandType::kRegCount); | |
| 889 int reg_count = static_cast<int>(operands[i + 1]); | |
| 890 if (reg_count == 0) { | |
| 891 return Register::FromOperand(operands[i]) == Register(0); | |
| 892 } else { | |
| 893 Register start = Register::FromOperand(operands[i]); | |
| 894 Register end(start.index() + reg_count - 1); | |
| 895 if (!RegisterIsValid(start) || !RegisterIsValid(end) || start > end) { | |
| 896 return false; | |
| 897 } | |
| 898 } | |
| 899 i++; // Skip past kRegCount operand. | |
| 900 break; | |
| 901 } | |
| 902 case OperandType::kReg: | |
| 903 case OperandType::kRegOut: { | |
| 904 Register reg = Register::FromOperand(operands[i]); | |
| 905 if (!RegisterIsValid(reg)) { | |
| 906 return false; | |
| 907 } | |
| 908 break; | |
| 909 } | |
| 910 case OperandType::kRegOutPair: | |
| 911 case OperandType::kRegPair: { | |
| 912 Register reg0 = Register::FromOperand(operands[i]); | |
| 913 Register reg1 = Register(reg0.index() + 1); | |
| 914 if (!RegisterIsValid(reg0) || !RegisterIsValid(reg1)) { | |
| 915 return false; | |
| 916 } | |
| 917 break; | |
| 918 } | |
| 919 case OperandType::kRegOutTriple: { | |
| 920 Register reg0 = Register::FromOperand(operands[i]); | |
| 921 Register reg1 = Register(reg0.index() + 1); | |
| 922 Register reg2 = Register(reg0.index() + 2); | |
| 923 if (!RegisterIsValid(reg0) || !RegisterIsValid(reg1) || | |
| 924 !RegisterIsValid(reg2)) { | |
| 925 return false; | |
| 926 } | |
| 927 break; | |
| 928 } | |
| 929 case OperandType::kRegCount: | |
| 930 UNREACHABLE(); // Dealt with in kRegList above. | |
| 931 } | |
| 932 } | |
| 933 | 957 |
| 934 return true; | 958 uint32_t BytecodeArrayBuilder::GetInputRegisterOperand(Register reg) { |
| 959 DCHECK(RegisterIsValid(reg)); |
| 960 if (register_optimizer_) reg = register_optimizer_->GetInputRegister(reg); |
| 961 return static_cast<uint32_t>(reg.ToOperand()); |
| 962 } |
| 963 |
| 964 uint32_t BytecodeArrayBuilder::GetOutputRegisterOperand(Register reg) { |
| 965 DCHECK(RegisterIsValid(reg)); |
| 966 if (register_optimizer_) register_optimizer_->PrepareOutputRegister(reg); |
| 967 return static_cast<uint32_t>(reg.ToOperand()); |
| 968 } |
| 969 |
| 970 uint32_t BytecodeArrayBuilder::GetInputRegisterListOperand( |
| 971 RegisterList reg_list) { |
| 972 DCHECK(RegisterListIsValid(reg_list)); |
| 973 if (register_optimizer_) |
| 974 reg_list = register_optimizer_->GetInputRegisterList(reg_list); |
| 975 return static_cast<uint32_t>(reg_list.first_register().ToOperand()); |
| 976 } |
| 977 |
| 978 uint32_t BytecodeArrayBuilder::GetOutputRegisterListOperand( |
| 979 RegisterList reg_list) { |
| 980 DCHECK(RegisterListIsValid(reg_list)); |
| 981 if (register_optimizer_) |
| 982 register_optimizer_->PrepareOutputRegisterList(reg_list); |
| 983 return static_cast<uint32_t>(reg_list.first_register().ToOperand()); |
| 935 } | 984 } |
| 936 | 985 |
| 937 } // namespace interpreter | 986 } // namespace interpreter |
| 938 } // namespace internal | 987 } // namespace internal |
| 939 } // namespace v8 | 988 } // namespace v8 |
| OLD | NEW |