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