| 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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 return reg.is_parameter() || reg.index() < locals_count(); | 73 return reg.is_parameter() || reg.index() < locals_count(); |
| 74 } | 74 } |
| 75 | 75 |
| 76 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) { | 76 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) { |
| 77 DCHECK(return_seen_in_block_); | 77 DCHECK(return_seen_in_block_); |
| 78 DCHECK(!bytecode_generated_); | 78 DCHECK(!bytecode_generated_); |
| 79 bytecode_generated_ = true; | 79 bytecode_generated_ = true; |
| 80 | 80 |
| 81 Handle<FixedArray> handler_table = | 81 Handle<FixedArray> handler_table = |
| 82 handler_table_builder()->ToHandlerTable(isolate); | 82 handler_table_builder()->ToHandlerTable(isolate); |
| 83 return pipeline_->ToBytecodeArray(isolate, | 83 return pipeline_->ToBytecodeArray(isolate, fixed_register_count(), |
| 84 fixed_and_temporary_register_count(), | |
| 85 parameter_count(), handler_table); | 84 parameter_count(), handler_table); |
| 86 } | 85 } |
| 87 | 86 |
| 87 namespace { |
| 88 |
| 89 static bool ExpressionPositionIsNeeded(Bytecode bytecode) { |
| 90 // An expression position is always needed if filtering is turned |
| 91 // off. Otherwise an expression is only needed if the bytecode has |
| 92 // external side effects. |
| 93 return !FLAG_ignition_filter_expression_positions || |
| 94 !Bytecodes::IsWithoutExternalSideEffects(bytecode); |
| 95 } |
| 96 |
| 97 } // namespace |
| 98 |
| 99 void BytecodeArrayBuilder::AttachSourceInfo(BytecodeNode* node) { |
| 100 if (latest_source_info_.is_valid()) { |
| 101 // Statement positions need to be emitted immediately. Expression |
| 102 // positions can be pushed back until a bytecode is found that can |
| 103 // throw. Hence we only invalidate the existing source position |
| 104 // information if it is used. |
| 105 if (latest_source_info_.is_statement() || |
| 106 ExpressionPositionIsNeeded(node->bytecode())) { |
| 107 node->source_info().Clone(latest_source_info_); |
| 108 latest_source_info_.set_invalid(); |
| 109 } |
| 110 } |
| 111 } |
| 112 |
| 88 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | 113 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, |
| 89 uint32_t operand1, uint32_t operand2, | 114 uint32_t operand1, uint32_t operand2, |
| 90 uint32_t operand3) { | 115 uint32_t operand3) { |
| 91 DCHECK(OperandsAreValid(bytecode, 4, operand0, operand1, operand2, operand3)); | 116 DCHECK(OperandsAreValid(bytecode, 4, operand0, operand1, operand2, operand3)); |
| 92 BytecodeNode node(bytecode, operand0, operand1, operand2, operand3, | 117 BytecodeNode node(bytecode, operand0, operand1, operand2, operand3); |
| 93 &latest_source_info_); | 118 AttachSourceInfo(&node); |
| 94 pipeline()->Write(&node); | 119 pipeline()->Write(&node); |
| 95 } | 120 } |
| 96 | 121 |
| 97 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | 122 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, |
| 98 uint32_t operand1, uint32_t operand2) { | 123 uint32_t operand1, uint32_t operand2) { |
| 99 DCHECK(OperandsAreValid(bytecode, 3, operand0, operand1, operand2)); | 124 DCHECK(OperandsAreValid(bytecode, 3, operand0, operand1, operand2)); |
| 100 BytecodeNode node(bytecode, operand0, operand1, operand2, | 125 BytecodeNode node(bytecode, operand0, operand1, operand2); |
| 101 &latest_source_info_); | 126 AttachSourceInfo(&node); |
| 102 pipeline()->Write(&node); | 127 pipeline()->Write(&node); |
| 103 } | 128 } |
| 104 | 129 |
| 105 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | 130 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, |
| 106 uint32_t operand1) { | 131 uint32_t operand1) { |
| 107 DCHECK(OperandsAreValid(bytecode, 2, operand0, operand1)); | 132 DCHECK(OperandsAreValid(bytecode, 2, operand0, operand1)); |
| 108 BytecodeNode node(bytecode, operand0, operand1, &latest_source_info_); | 133 BytecodeNode node(bytecode, operand0, operand1); |
| 134 AttachSourceInfo(&node); |
| 109 pipeline()->Write(&node); | 135 pipeline()->Write(&node); |
| 110 } | 136 } |
| 111 | 137 |
| 112 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0) { | 138 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0) { |
| 113 DCHECK(OperandsAreValid(bytecode, 1, operand0)); | 139 DCHECK(OperandsAreValid(bytecode, 1, operand0)); |
| 114 BytecodeNode node(bytecode, operand0, &latest_source_info_); | 140 BytecodeNode node(bytecode, operand0); |
| 141 AttachSourceInfo(&node); |
| 115 pipeline()->Write(&node); | 142 pipeline()->Write(&node); |
| 116 } | 143 } |
| 117 | 144 |
| 118 void BytecodeArrayBuilder::Output(Bytecode bytecode) { | 145 void BytecodeArrayBuilder::Output(Bytecode bytecode) { |
| 119 DCHECK(OperandsAreValid(bytecode, 0)); | 146 DCHECK(OperandsAreValid(bytecode, 0)); |
| 120 BytecodeNode node(bytecode, &latest_source_info_); | 147 BytecodeNode node(bytecode); |
| 148 AttachSourceInfo(&node); |
| 121 pipeline()->Write(&node); | 149 pipeline()->Write(&node); |
| 122 } | 150 } |
| 123 | 151 |
| 124 void BytecodeArrayBuilder::OutputJump(Bytecode bytecode, BytecodeLabel* label) { | |
| 125 BytecodeNode node(bytecode, 0, &latest_source_info_); | |
| 126 pipeline_->WriteJump(&node, label); | |
| 127 LeaveBasicBlock(); | |
| 128 } | |
| 129 | |
| 130 void BytecodeArrayBuilder::OutputJump(Bytecode bytecode, uint32_t operand0, | |
| 131 BytecodeLabel* label) { | |
| 132 BytecodeNode node(bytecode, 0, operand0, &latest_source_info_); | |
| 133 pipeline_->WriteJump(&node, label); | |
| 134 LeaveBasicBlock(); | |
| 135 } | |
| 136 | |
| 137 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, | 152 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, |
| 138 Register reg, | 153 Register reg, |
| 139 int feedback_slot) { | 154 int feedback_slot) { |
| 140 switch (op) { | 155 Output(BytecodeForBinaryOperation(op), RegisterOperand(reg), |
| 141 case Token::Value::ADD: | 156 UnsignedOperand(feedback_slot)); |
| 142 Output(Bytecode::kAdd, RegisterOperand(reg), | |
| 143 UnsignedOperand(feedback_slot)); | |
| 144 break; | |
| 145 case Token::Value::SUB: | |
| 146 Output(Bytecode::kSub, RegisterOperand(reg), | |
| 147 UnsignedOperand(feedback_slot)); | |
| 148 break; | |
| 149 case Token::Value::MUL: | |
| 150 Output(Bytecode::kMul, RegisterOperand(reg), | |
| 151 UnsignedOperand(feedback_slot)); | |
| 152 break; | |
| 153 case Token::Value::DIV: | |
| 154 Output(Bytecode::kDiv, RegisterOperand(reg), | |
| 155 UnsignedOperand(feedback_slot)); | |
| 156 break; | |
| 157 case Token::Value::MOD: | |
| 158 Output(Bytecode::kMod, RegisterOperand(reg), | |
| 159 UnsignedOperand(feedback_slot)); | |
| 160 break; | |
| 161 case Token::Value::BIT_OR: | |
| 162 Output(Bytecode::kBitwiseOr, RegisterOperand(reg), | |
| 163 UnsignedOperand(feedback_slot)); | |
| 164 break; | |
| 165 case Token::Value::BIT_XOR: | |
| 166 Output(Bytecode::kBitwiseXor, RegisterOperand(reg), | |
| 167 UnsignedOperand(feedback_slot)); | |
| 168 break; | |
| 169 case Token::Value::BIT_AND: | |
| 170 Output(Bytecode::kBitwiseAnd, RegisterOperand(reg), | |
| 171 UnsignedOperand(feedback_slot)); | |
| 172 break; | |
| 173 case Token::Value::SHL: | |
| 174 Output(Bytecode::kShiftLeft, RegisterOperand(reg), | |
| 175 UnsignedOperand(feedback_slot)); | |
| 176 break; | |
| 177 case Token::Value::SAR: | |
| 178 Output(Bytecode::kShiftRight, RegisterOperand(reg), | |
| 179 UnsignedOperand(feedback_slot)); | |
| 180 break; | |
| 181 case Token::Value::SHR: | |
| 182 Output(Bytecode::kShiftRightLogical, RegisterOperand(reg), | |
| 183 UnsignedOperand(feedback_slot)); | |
| 184 break; | |
| 185 default: | |
| 186 UNREACHABLE(); | |
| 187 } | |
| 188 return *this; | 157 return *this; |
| 189 } | 158 } |
| 190 | 159 |
| 191 BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op, | 160 BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op, |
| 192 int feedback_slot) { | 161 int feedback_slot) { |
| 193 if (op == Token::Value::ADD) { | 162 Output(BytecodeForCountOperation(op), UnsignedOperand(feedback_slot)); |
| 194 Output(Bytecode::kInc, UnsignedOperand(feedback_slot)); | |
| 195 } else { | |
| 196 DCHECK_EQ(op, Token::Value::SUB); | |
| 197 Output(Bytecode::kDec, UnsignedOperand(feedback_slot)); | |
| 198 } | |
| 199 return *this; | 163 return *this; |
| 200 } | 164 } |
| 201 | 165 |
| 202 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() { | 166 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() { |
| 203 Output(Bytecode::kToBooleanLogicalNot); | 167 Output(Bytecode::kToBooleanLogicalNot); |
| 204 return *this; | 168 return *this; |
| 205 } | 169 } |
| 206 | 170 |
| 171 |
| 207 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() { | 172 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() { |
| 208 Output(Bytecode::kTypeOf); | 173 Output(Bytecode::kTypeOf); |
| 209 return *this; | 174 return *this; |
| 210 } | 175 } |
| 211 | 176 |
| 212 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation( | 177 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation( |
| 213 Token::Value op, Register reg, int feedback_slot) { | 178 Token::Value op, Register reg, int feedback_slot) { |
| 214 switch (op) { | 179 if (op == Token::INSTANCEOF || op == Token::IN) { |
| 215 case Token::Value::EQ: | 180 Output(BytecodeForCompareOperation(op), RegisterOperand(reg)); |
| 216 Output(Bytecode::kTestEqual, RegisterOperand(reg), | 181 } else { |
| 217 UnsignedOperand(feedback_slot)); | 182 Output(BytecodeForCompareOperation(op), RegisterOperand(reg), |
| 218 break; | 183 UnsignedOperand(feedback_slot)); |
| 219 case Token::Value::NE: | |
| 220 Output(Bytecode::kTestNotEqual, RegisterOperand(reg), | |
| 221 UnsignedOperand(feedback_slot)); | |
| 222 break; | |
| 223 case Token::Value::EQ_STRICT: | |
| 224 Output(Bytecode::kTestEqualStrict, RegisterOperand(reg), | |
| 225 UnsignedOperand(feedback_slot)); | |
| 226 break; | |
| 227 case Token::Value::LT: | |
| 228 Output(Bytecode::kTestLessThan, RegisterOperand(reg), | |
| 229 UnsignedOperand(feedback_slot)); | |
| 230 break; | |
| 231 case Token::Value::GT: | |
| 232 Output(Bytecode::kTestGreaterThan, RegisterOperand(reg), | |
| 233 UnsignedOperand(feedback_slot)); | |
| 234 break; | |
| 235 case Token::Value::LTE: | |
| 236 Output(Bytecode::kTestLessThanOrEqual, RegisterOperand(reg), | |
| 237 UnsignedOperand(feedback_slot)); | |
| 238 break; | |
| 239 case Token::Value::GTE: | |
| 240 Output(Bytecode::kTestGreaterThanOrEqual, RegisterOperand(reg), | |
| 241 UnsignedOperand(feedback_slot)); | |
| 242 break; | |
| 243 case Token::Value::INSTANCEOF: | |
| 244 Output(Bytecode::kTestInstanceOf, RegisterOperand(reg)); | |
| 245 break; | |
| 246 case Token::Value::IN: | |
| 247 Output(Bytecode::kTestIn, RegisterOperand(reg)); | |
| 248 break; | |
| 249 default: | |
| 250 UNREACHABLE(); | |
| 251 } | 184 } |
| 252 return *this; | 185 return *this; |
| 253 } | 186 } |
| 254 | 187 |
| 255 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry( | 188 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry( |
| 256 size_t entry) { | 189 size_t entry) { |
| 257 Output(Bytecode::kLdaConstant, UnsignedOperand(entry)); | 190 Output(Bytecode::kLdaConstant, UnsignedOperand(entry)); |
| 258 return *this; | 191 return *this; |
| 259 } | 192 } |
| 260 | 193 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 | 247 |
| 315 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, | 248 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, |
| 316 Register to) { | 249 Register to) { |
| 317 DCHECK(from != to); | 250 DCHECK(from != to); |
| 318 Output(Bytecode::kMov, RegisterOperand(from), RegisterOperand(to)); | 251 Output(Bytecode::kMov, RegisterOperand(from), RegisterOperand(to)); |
| 319 return *this; | 252 return *this; |
| 320 } | 253 } |
| 321 | 254 |
| 322 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(int feedback_slot, | 255 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(int feedback_slot, |
| 323 TypeofMode typeof_mode) { | 256 TypeofMode typeof_mode) { |
| 324 if (typeof_mode == INSIDE_TYPEOF) { | 257 // TODO(rmcilroy): Potentially store typeof information in an |
| 325 Output(Bytecode::kLdaGlobalInsideTypeof, feedback_slot); | 258 // operand rather than having extra bytecodes. |
| 326 } else { | 259 Bytecode bytecode = BytecodeForLoadGlobal(typeof_mode); |
| 327 DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF); | 260 Output(bytecode, UnsignedOperand(feedback_slot)); |
| 328 Output(Bytecode::kLdaGlobal, UnsignedOperand(feedback_slot)); | |
| 329 } | |
| 330 return *this; | 261 return *this; |
| 331 } | 262 } |
| 332 | 263 |
| 333 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal( | 264 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal( |
| 334 const Handle<String> name, int feedback_slot, LanguageMode language_mode) { | 265 const Handle<String> name, int feedback_slot, LanguageMode language_mode) { |
| 266 Bytecode bytecode = BytecodeForStoreGlobal(language_mode); |
| 335 size_t name_index = GetConstantPoolEntry(name); | 267 size_t name_index = GetConstantPoolEntry(name); |
| 336 if (language_mode == SLOPPY) { | 268 Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); |
| 337 Output(Bytecode::kStaGlobalSloppy, UnsignedOperand(name_index), | |
| 338 UnsignedOperand(feedback_slot)); | |
| 339 } else { | |
| 340 DCHECK_EQ(language_mode, STRICT); | |
| 341 Output(Bytecode::kStaGlobalStrict, UnsignedOperand(name_index), | |
| 342 UnsignedOperand(feedback_slot)); | |
| 343 } | |
| 344 return *this; | 269 return *this; |
| 345 } | 270 } |
| 346 | 271 |
| 347 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context, | 272 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context, |
| 348 int slot_index, | 273 int slot_index, |
| 349 int depth) { | 274 int depth) { |
| 350 Output(Bytecode::kLdaContextSlot, RegisterOperand(context), | 275 Output(Bytecode::kLdaContextSlot, RegisterOperand(context), |
| 351 UnsignedOperand(slot_index), UnsignedOperand(depth)); | 276 UnsignedOperand(slot_index), UnsignedOperand(depth)); |
| 352 return *this; | 277 return *this; |
| 353 } | 278 } |
| 354 | 279 |
| 355 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context, | 280 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context, |
| 356 int slot_index, | 281 int slot_index, |
| 357 int depth) { | 282 int depth) { |
| 358 Output(Bytecode::kStaContextSlot, RegisterOperand(context), | 283 Output(Bytecode::kStaContextSlot, RegisterOperand(context), |
| 359 UnsignedOperand(slot_index), UnsignedOperand(depth)); | 284 UnsignedOperand(slot_index), UnsignedOperand(depth)); |
| 360 return *this; | 285 return *this; |
| 361 } | 286 } |
| 362 | 287 |
| 363 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot( | 288 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot( |
| 364 const Handle<String> name, TypeofMode typeof_mode) { | 289 const Handle<String> name, TypeofMode typeof_mode) { |
| 290 Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF) |
| 291 ? Bytecode::kLdaLookupSlotInsideTypeof |
| 292 : Bytecode::kLdaLookupSlot; |
| 365 size_t name_index = GetConstantPoolEntry(name); | 293 size_t name_index = GetConstantPoolEntry(name); |
| 366 if (typeof_mode == INSIDE_TYPEOF) { | 294 Output(bytecode, UnsignedOperand(name_index)); |
| 367 Output(Bytecode::kLdaLookupSlotInsideTypeof, UnsignedOperand(name_index)); | |
| 368 } else { | |
| 369 DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF); | |
| 370 Output(Bytecode::kLdaLookupSlot, UnsignedOperand(name_index)); | |
| 371 } | |
| 372 return *this; | 295 return *this; |
| 373 } | 296 } |
| 374 | 297 |
| 375 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupContextSlot( | 298 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupContextSlot( |
| 376 const Handle<String> name, TypeofMode typeof_mode, int slot_index, | 299 const Handle<String> name, TypeofMode typeof_mode, int slot_index, |
| 377 int depth) { | 300 int depth) { |
| 378 Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF) | 301 Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF) |
| 379 ? Bytecode::kLdaLookupContextSlotInsideTypeof | 302 ? Bytecode::kLdaLookupContextSlotInsideTypeof |
| 380 : Bytecode::kLdaLookupContextSlot; | 303 : Bytecode::kLdaLookupContextSlot; |
| 381 size_t name_index = GetConstantPoolEntry(name); | 304 size_t name_index = GetConstantPoolEntry(name); |
| 382 Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(slot_index), | 305 Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(slot_index), |
| 383 UnsignedOperand(depth)); | 306 UnsignedOperand(depth)); |
| 384 return *this; | 307 return *this; |
| 385 } | 308 } |
| 386 | 309 |
| 387 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupGlobalSlot( | 310 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupGlobalSlot( |
| 388 const Handle<String> name, TypeofMode typeof_mode, int feedback_slot, | 311 const Handle<String> name, TypeofMode typeof_mode, int feedback_slot, |
| 389 int depth) { | 312 int depth) { |
| 390 Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF) | 313 Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF) |
| 391 ? Bytecode::kLdaLookupGlobalSlotInsideTypeof | 314 ? Bytecode::kLdaLookupGlobalSlotInsideTypeof |
| 392 : Bytecode::kLdaLookupGlobalSlot; | 315 : Bytecode::kLdaLookupGlobalSlot; |
| 393 size_t name_index = GetConstantPoolEntry(name); | 316 size_t name_index = GetConstantPoolEntry(name); |
| 394 Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(feedback_slot), | 317 Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(feedback_slot), |
| 395 UnsignedOperand(depth)); | 318 UnsignedOperand(depth)); |
| 396 return *this; | 319 return *this; |
| 397 } | 320 } |
| 398 | 321 |
| 399 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot( | 322 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot( |
| 400 const Handle<String> name, LanguageMode language_mode) { | 323 const Handle<String> name, LanguageMode language_mode) { |
| 324 Bytecode bytecode = BytecodeForStoreLookupSlot(language_mode); |
| 401 size_t name_index = GetConstantPoolEntry(name); | 325 size_t name_index = GetConstantPoolEntry(name); |
| 402 if (language_mode == SLOPPY) { | 326 Output(bytecode, UnsignedOperand(name_index)); |
| 403 Output(Bytecode::kStaLookupSlotSloppy, UnsignedOperand(name_index)); | |
| 404 } else { | |
| 405 DCHECK_EQ(language_mode, STRICT); | |
| 406 Output(Bytecode::kStaLookupSlotStrict, UnsignedOperand(name_index)); | |
| 407 } | |
| 408 return *this; | 327 return *this; |
| 409 } | 328 } |
| 410 | 329 |
| 411 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( | 330 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( |
| 412 Register object, const Handle<Name> name, int feedback_slot) { | 331 Register object, const Handle<Name> name, int feedback_slot) { |
| 413 size_t name_index = GetConstantPoolEntry(name); | 332 size_t name_index = GetConstantPoolEntry(name); |
| 414 Output(Bytecode::kLdaNamedProperty, RegisterOperand(object), | 333 Output(Bytecode::kLdaNamedProperty, RegisterOperand(object), |
| 415 UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); | 334 UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); |
| 416 return *this; | 335 return *this; |
| 417 } | 336 } |
| 418 | 337 |
| 419 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( | 338 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( |
| 420 Register object, int feedback_slot) { | 339 Register object, int feedback_slot) { |
| 421 Output(Bytecode::kLdaKeyedProperty, RegisterOperand(object), | 340 Output(Bytecode::kLdaKeyedProperty, RegisterOperand(object), |
| 422 UnsignedOperand(feedback_slot)); | 341 UnsignedOperand(feedback_slot)); |
| 423 return *this; | 342 return *this; |
| 424 } | 343 } |
| 425 | 344 |
| 426 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( | 345 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( |
| 427 Register object, const Handle<Name> name, int feedback_slot, | 346 Register object, const Handle<Name> name, int feedback_slot, |
| 428 LanguageMode language_mode) { | 347 LanguageMode language_mode) { |
| 348 Bytecode bytecode = BytecodeForStoreNamedProperty(language_mode); |
| 429 size_t name_index = GetConstantPoolEntry(name); | 349 size_t name_index = GetConstantPoolEntry(name); |
| 430 if (language_mode == SLOPPY) { | 350 Output(bytecode, RegisterOperand(object), UnsignedOperand(name_index), |
| 431 Output(Bytecode::kStaNamedPropertySloppy, RegisterOperand(object), | 351 UnsignedOperand(feedback_slot)); |
| 432 UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); | |
| 433 } else { | |
| 434 DCHECK_EQ(language_mode, STRICT); | |
| 435 Output(Bytecode::kStaNamedPropertyStrict, RegisterOperand(object), | |
| 436 UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); | |
| 437 } | |
| 438 return *this; | 352 return *this; |
| 439 } | 353 } |
| 440 | 354 |
| 441 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( | 355 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( |
| 442 Register object, Register key, int feedback_slot, | 356 Register object, Register key, int feedback_slot, |
| 443 LanguageMode language_mode) { | 357 LanguageMode language_mode) { |
| 444 if (language_mode == SLOPPY) { | 358 Bytecode bytecode = BytecodeForStoreKeyedProperty(language_mode); |
| 445 Output(Bytecode::kStaKeyedPropertySloppy, RegisterOperand(object), | 359 Output(bytecode, RegisterOperand(object), RegisterOperand(key), |
| 446 RegisterOperand(key), UnsignedOperand(feedback_slot)); | 360 UnsignedOperand(feedback_slot)); |
| 447 } else { | |
| 448 DCHECK_EQ(language_mode, STRICT); | |
| 449 Output(Bytecode::kStaKeyedPropertyStrict, RegisterOperand(object), | |
| 450 RegisterOperand(key), UnsignedOperand(feedback_slot)); | |
| 451 } | |
| 452 return *this; | 361 return *this; |
| 453 } | 362 } |
| 454 | 363 |
| 455 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(size_t entry, | 364 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(size_t entry, |
| 456 int flags) { | 365 int flags) { |
| 457 Output(Bytecode::kCreateClosure, UnsignedOperand(entry), | 366 Output(Bytecode::kCreateClosure, UnsignedOperand(entry), |
| 458 UnsignedOperand(flags)); | 367 UnsignedOperand(flags)); |
| 459 return *this; | 368 return *this; |
| 460 } | 369 } |
| 461 | 370 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 483 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext( | 392 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext( |
| 484 Register object, Handle<ScopeInfo> scope_info) { | 393 Register object, Handle<ScopeInfo> scope_info) { |
| 485 size_t scope_info_index = GetConstantPoolEntry(scope_info); | 394 size_t scope_info_index = GetConstantPoolEntry(scope_info); |
| 486 Output(Bytecode::kCreateWithContext, RegisterOperand(object), | 395 Output(Bytecode::kCreateWithContext, RegisterOperand(object), |
| 487 UnsignedOperand(scope_info_index)); | 396 UnsignedOperand(scope_info_index)); |
| 488 return *this; | 397 return *this; |
| 489 } | 398 } |
| 490 | 399 |
| 491 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments( | 400 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments( |
| 492 CreateArgumentsType type) { | 401 CreateArgumentsType type) { |
| 493 switch (type) { | 402 // TODO(rmcilroy): Consider passing the type as a bytecode operand rather |
| 494 case CreateArgumentsType::kMappedArguments: | 403 // than having two different bytecodes once we have better support for |
| 495 Output(Bytecode::kCreateMappedArguments); | 404 // branches in the InterpreterAssembler. |
| 496 break; | 405 Bytecode bytecode = BytecodeForCreateArguments(type); |
| 497 case CreateArgumentsType::kUnmappedArguments: | 406 Output(bytecode); |
| 498 Output(Bytecode::kCreateUnmappedArguments); | |
| 499 break; | |
| 500 case CreateArgumentsType::kRestParameter: | |
| 501 Output(Bytecode::kCreateRestParameter); | |
| 502 break; | |
| 503 default: | |
| 504 UNREACHABLE(); | |
| 505 } | |
| 506 return *this; | 407 return *this; |
| 507 } | 408 } |
| 508 | 409 |
| 509 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral( | 410 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral( |
| 510 Handle<String> pattern, int literal_index, int flags) { | 411 Handle<String> pattern, int literal_index, int flags) { |
| 511 size_t pattern_entry = GetConstantPoolEntry(pattern); | 412 size_t pattern_entry = GetConstantPoolEntry(pattern); |
| 512 Output(Bytecode::kCreateRegExpLiteral, UnsignedOperand(pattern_entry), | 413 Output(Bytecode::kCreateRegExpLiteral, UnsignedOperand(pattern_entry), |
| 513 UnsignedOperand(literal_index), UnsignedOperand(flags)); | 414 UnsignedOperand(literal_index), UnsignedOperand(flags)); |
| 514 return *this; | 415 return *this; |
| 515 } | 416 } |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 568 return *this; | 469 return *this; |
| 569 } | 470 } |
| 570 | 471 |
| 571 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target, | 472 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target, |
| 572 BytecodeLabel* label) { | 473 BytecodeLabel* label) { |
| 573 pipeline_->BindLabel(target, label); | 474 pipeline_->BindLabel(target, label); |
| 574 LeaveBasicBlock(); | 475 LeaveBasicBlock(); |
| 575 return *this; | 476 return *this; |
| 576 } | 477 } |
| 577 | 478 |
| 479 BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(BytecodeNode* node, |
| 480 BytecodeLabel* label) { |
| 481 AttachSourceInfo(node); |
| 482 pipeline_->WriteJump(node, label); |
| 483 LeaveBasicBlock(); |
| 484 return *this; |
| 485 } |
| 486 |
| 578 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { | 487 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { |
| 579 OutputJump(Bytecode::kJump, label); | 488 BytecodeNode node(Bytecode::kJump, 0); |
| 580 return *this; | 489 return OutputJump(&node, label); |
| 581 } | 490 } |
| 582 | 491 |
| 583 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) { | 492 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) { |
| 584 // The peephole optimizer attempts to simplify JumpIfToBooleanTrue | 493 // The peephole optimizer attempts to simplify JumpIfToBooleanTrue |
| 585 // to JumpIfTrue. | 494 // to JumpIfTrue. |
| 586 OutputJump(Bytecode::kJumpIfToBooleanTrue, label); | 495 BytecodeNode node(Bytecode::kJumpIfToBooleanTrue, 0); |
| 587 return *this; | 496 return OutputJump(&node, label); |
| 588 } | 497 } |
| 589 | 498 |
| 590 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) { | 499 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) { |
| 591 OutputJump(Bytecode::kJumpIfToBooleanFalse, label); | 500 // The peephole optimizer attempts to simplify JumpIfToBooleanFalse |
| 592 return *this; | 501 // to JumpIfFalse. |
| 502 BytecodeNode node(Bytecode::kJumpIfToBooleanFalse, 0); |
| 503 return OutputJump(&node, label); |
| 593 } | 504 } |
| 594 | 505 |
| 595 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) { | 506 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) { |
| 596 OutputJump(Bytecode::kJumpIfNull, label); | 507 BytecodeNode node(Bytecode::kJumpIfNull, 0); |
| 597 return *this; | 508 return OutputJump(&node, label); |
| 598 } | 509 } |
| 599 | 510 |
| 600 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined( | 511 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined( |
| 601 BytecodeLabel* label) { | 512 BytecodeLabel* label) { |
| 602 OutputJump(Bytecode::kJumpIfUndefined, label); | 513 BytecodeNode node(Bytecode::kJumpIfUndefined, 0); |
| 603 return *this; | 514 return OutputJump(&node, label); |
| 604 } | 515 } |
| 605 | 516 |
| 606 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole( | 517 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole( |
| 607 BytecodeLabel* label) { | 518 BytecodeLabel* label) { |
| 608 OutputJump(Bytecode::kJumpIfNotHole, label); | 519 BytecodeNode node(Bytecode::kJumpIfNotHole, 0); |
| 609 return *this; | 520 return OutputJump(&node, label); |
| 610 } | 521 } |
| 611 | 522 |
| 612 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label, | 523 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label, |
| 613 int loop_depth) { | 524 int loop_depth) { |
| 614 OutputJump(Bytecode::kJumpLoop, UnsignedOperand(loop_depth), label); | 525 BytecodeNode node(Bytecode::kJumpLoop, 0, UnsignedOperand(loop_depth)); |
| 615 return *this; | 526 return OutputJump(&node, label); |
| 616 } | 527 } |
| 617 | 528 |
| 618 BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) { | 529 BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) { |
| 619 if (position != kNoSourcePosition) { | 530 if (position != kNoSourcePosition) { |
| 620 // We need to attach a non-breakable source position to a stack | 531 // We need to attach a non-breakable source position to a stack |
| 621 // check, so we simply add it as expression position. There can be | 532 // check, so we simply add it as expression position. There can be |
| 622 // a prior statement position from constructs like: | 533 // a prior statement position from constructs like: |
| 623 // | 534 // |
| 624 // do var x; while (false); | 535 // do var x; while (false); |
| 625 // | 536 // |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 726 Return(); | 637 Return(); |
| 727 } | 638 } |
| 728 DCHECK(return_seen_in_block_); | 639 DCHECK(return_seen_in_block_); |
| 729 } | 640 } |
| 730 | 641 |
| 731 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, | 642 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, |
| 732 Register receiver_args, | 643 Register receiver_args, |
| 733 size_t receiver_args_count, | 644 size_t receiver_args_count, |
| 734 int feedback_slot, | 645 int feedback_slot, |
| 735 TailCallMode tail_call_mode) { | 646 TailCallMode tail_call_mode) { |
| 736 if (tail_call_mode == TailCallMode::kDisallow) { | 647 Bytecode bytecode = BytecodeForCall(tail_call_mode); |
| 737 Output(Bytecode::kCall, RegisterOperand(callable), | 648 Output(bytecode, RegisterOperand(callable), RegisterOperand(receiver_args), |
| 738 RegisterOperand(receiver_args), UnsignedOperand(receiver_args_count), | 649 UnsignedOperand(receiver_args_count), UnsignedOperand(feedback_slot)); |
| 739 UnsignedOperand(feedback_slot)); | |
| 740 } else { | |
| 741 DCHECK(tail_call_mode == TailCallMode::kAllow); | |
| 742 Output(Bytecode::kTailCall, RegisterOperand(callable), | |
| 743 RegisterOperand(receiver_args), UnsignedOperand(receiver_args_count), | |
| 744 UnsignedOperand(feedback_slot)); | |
| 745 } | |
| 746 return *this; | 650 return *this; |
| 747 } | 651 } |
| 748 | 652 |
| 749 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, | 653 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, |
| 750 Register first_arg, | 654 Register first_arg, |
| 751 size_t arg_count, | 655 size_t arg_count, |
| 752 int feedback_slot_id) { | 656 int feedback_slot_id) { |
| 753 if (!first_arg.is_valid()) { | 657 if (!first_arg.is_valid()) { |
| 754 DCHECK_EQ(0u, arg_count); | 658 DCHECK_EQ(0u, arg_count); |
| 755 first_arg = Register(0); | 659 first_arg = Register(0); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 798 | 702 |
| 799 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime( | 703 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime( |
| 800 int context_index, Register receiver_args, size_t receiver_args_count) { | 704 int context_index, Register receiver_args, size_t receiver_args_count) { |
| 801 Output(Bytecode::kCallJSRuntime, UnsignedOperand(context_index), | 705 Output(Bytecode::kCallJSRuntime, UnsignedOperand(context_index), |
| 802 RegisterOperand(receiver_args), UnsignedOperand(receiver_args_count)); | 706 RegisterOperand(receiver_args), UnsignedOperand(receiver_args_count)); |
| 803 return *this; | 707 return *this; |
| 804 } | 708 } |
| 805 | 709 |
| 806 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, | 710 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, |
| 807 LanguageMode language_mode) { | 711 LanguageMode language_mode) { |
| 808 if (language_mode == SLOPPY) { | 712 Output(BytecodeForDelete(language_mode), RegisterOperand(object)); |
| 809 Output(Bytecode::kDeletePropertySloppy, RegisterOperand(object)); | |
| 810 } else { | |
| 811 DCHECK_EQ(language_mode, STRICT); | |
| 812 Output(Bytecode::kDeletePropertyStrict, RegisterOperand(object)); | |
| 813 } | |
| 814 return *this; | 713 return *this; |
| 815 } | 714 } |
| 816 | 715 |
| 817 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { | 716 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { |
| 818 return constant_array_builder()->Insert(object); | 717 return constant_array_builder()->Insert(object); |
| 819 } | 718 } |
| 820 | 719 |
| 821 size_t BytecodeArrayBuilder::AllocateConstantPoolEntry() { | 720 size_t BytecodeArrayBuilder::AllocateConstantPoolEntry() { |
| 822 return constant_array_builder()->AllocateEntry(); | 721 return constant_array_builder()->AllocateEntry(); |
| 823 } | 722 } |
| 824 | 723 |
| 825 void BytecodeArrayBuilder::InsertConstantPoolEntryAt(size_t entry, | 724 void BytecodeArrayBuilder::InsertConstantPoolEntryAt(size_t entry, |
| 826 Handle<Object> object) { | 725 Handle<Object> object) { |
| 827 constant_array_builder()->InsertAllocatedEntry(entry, object); | 726 constant_array_builder()->InsertAllocatedEntry(entry, object); |
| 828 } | 727 } |
| 829 | 728 |
| 830 void BytecodeArrayBuilder::SetReturnPosition() { | 729 void BytecodeArrayBuilder::SetReturnPosition() { |
| 831 if (return_position_ == kNoSourcePosition) return; | 730 if (return_position_ == kNoSourcePosition) return; |
| 832 latest_source_info_.MakeStatementPosition(return_position_); | 731 latest_source_info_.MakeStatementPosition(return_position_); |
| 833 } | 732 } |
| 834 | 733 |
| 734 void BytecodeArrayBuilder::SetStatementPosition(Statement* stmt) { |
| 735 if (stmt->position() == kNoSourcePosition) return; |
| 736 latest_source_info_.MakeStatementPosition(stmt->position()); |
| 737 } |
| 738 |
| 739 void BytecodeArrayBuilder::SetExpressionPosition(Expression* expr) { |
| 740 if (expr->position() == kNoSourcePosition) return; |
| 741 if (!latest_source_info_.is_statement()) { |
| 742 // Ensure the current expression position is overwritten with the |
| 743 // latest value. |
| 744 latest_source_info_.MakeExpressionPosition(expr->position()); |
| 745 } |
| 746 } |
| 747 |
| 748 void BytecodeArrayBuilder::SetExpressionAsStatementPosition(Expression* expr) { |
| 749 if (expr->position() == kNoSourcePosition) return; |
| 750 latest_source_info_.MakeStatementPosition(expr->position()); |
| 751 } |
| 752 |
| 835 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { | 753 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { |
| 836 return temporary_register_allocator()->RegisterIsLive(reg); | 754 return temporary_register_allocator()->RegisterIsLive(reg); |
| 837 } | 755 } |
| 838 | 756 |
| 839 bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const { | 757 bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const { |
| 840 if (!reg.is_valid()) { | 758 if (!reg.is_valid()) { |
| 841 return false; | 759 return false; |
| 842 } | 760 } |
| 843 | 761 |
| 844 if (reg.is_current_context() || reg.is_function_closure() || | 762 if (reg.is_current_context() || reg.is_function_closure() || |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 888 } | 806 } |
| 889 break; | 807 break; |
| 890 case OperandType::kRuntimeId: | 808 case OperandType::kRuntimeId: |
| 891 if (Bytecodes::SizeForUnsignedOperand(operands[i]) > | 809 if (Bytecodes::SizeForUnsignedOperand(operands[i]) > |
| 892 OperandSize::kShort) { | 810 OperandSize::kShort) { |
| 893 return false; | 811 return false; |
| 894 } | 812 } |
| 895 break; | 813 break; |
| 896 case OperandType::kIdx: | 814 case OperandType::kIdx: |
| 897 // TODO(leszeks): Possibly split this up into constant pool indices and | 815 // TODO(leszeks): Possibly split this up into constant pool indices and |
| 898 // other indices, for checking. | 816 // other indices, for checking |
| 899 break; | 817 break; |
| 900 case OperandType::kUImm: | 818 case OperandType::kUImm: |
| 901 case OperandType::kImm: | 819 case OperandType::kImm: |
| 902 break; | 820 break; |
| 903 case OperandType::kMaybeReg: | 821 case OperandType::kMaybeReg: |
| 904 if (Register::FromOperand(operands[i]) == Register(0)) { | 822 if (Register::FromOperand(operands[i]) == Register(0)) { |
| 905 break; | 823 break; |
| 906 } | 824 } |
| 907 // Fall-through to kReg case. | 825 // Fall-through to kReg case. |
| 908 case OperandType::kReg: | 826 case OperandType::kReg: |
| (...skipping 22 matching lines...) Expand all Loading... |
| 931 return false; | 849 return false; |
| 932 } | 850 } |
| 933 break; | 851 break; |
| 934 } | 852 } |
| 935 } | 853 } |
| 936 } | 854 } |
| 937 | 855 |
| 938 return true; | 856 return true; |
| 939 } | 857 } |
| 940 | 858 |
| 859 // static |
| 860 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) { |
| 861 switch (op) { |
| 862 case Token::Value::ADD: |
| 863 return Bytecode::kAdd; |
| 864 case Token::Value::SUB: |
| 865 return Bytecode::kSub; |
| 866 case Token::Value::MUL: |
| 867 return Bytecode::kMul; |
| 868 case Token::Value::DIV: |
| 869 return Bytecode::kDiv; |
| 870 case Token::Value::MOD: |
| 871 return Bytecode::kMod; |
| 872 case Token::Value::BIT_OR: |
| 873 return Bytecode::kBitwiseOr; |
| 874 case Token::Value::BIT_XOR: |
| 875 return Bytecode::kBitwiseXor; |
| 876 case Token::Value::BIT_AND: |
| 877 return Bytecode::kBitwiseAnd; |
| 878 case Token::Value::SHL: |
| 879 return Bytecode::kShiftLeft; |
| 880 case Token::Value::SAR: |
| 881 return Bytecode::kShiftRight; |
| 882 case Token::Value::SHR: |
| 883 return Bytecode::kShiftRightLogical; |
| 884 default: |
| 885 UNREACHABLE(); |
| 886 return Bytecode::kIllegal; |
| 887 } |
| 888 } |
| 889 |
| 890 // static |
| 891 Bytecode BytecodeArrayBuilder::BytecodeForCountOperation(Token::Value op) { |
| 892 switch (op) { |
| 893 case Token::Value::ADD: |
| 894 return Bytecode::kInc; |
| 895 case Token::Value::SUB: |
| 896 return Bytecode::kDec; |
| 897 default: |
| 898 UNREACHABLE(); |
| 899 return Bytecode::kIllegal; |
| 900 } |
| 901 } |
| 902 |
| 903 // static |
| 904 Bytecode BytecodeArrayBuilder::BytecodeForCompareOperation(Token::Value op) { |
| 905 switch (op) { |
| 906 case Token::Value::EQ: |
| 907 return Bytecode::kTestEqual; |
| 908 case Token::Value::NE: |
| 909 return Bytecode::kTestNotEqual; |
| 910 case Token::Value::EQ_STRICT: |
| 911 return Bytecode::kTestEqualStrict; |
| 912 case Token::Value::LT: |
| 913 return Bytecode::kTestLessThan; |
| 914 case Token::Value::GT: |
| 915 return Bytecode::kTestGreaterThan; |
| 916 case Token::Value::LTE: |
| 917 return Bytecode::kTestLessThanOrEqual; |
| 918 case Token::Value::GTE: |
| 919 return Bytecode::kTestGreaterThanOrEqual; |
| 920 case Token::Value::INSTANCEOF: |
| 921 return Bytecode::kTestInstanceOf; |
| 922 case Token::Value::IN: |
| 923 return Bytecode::kTestIn; |
| 924 default: |
| 925 UNREACHABLE(); |
| 926 return Bytecode::kIllegal; |
| 927 } |
| 928 } |
| 929 |
| 930 // static |
| 931 Bytecode BytecodeArrayBuilder::BytecodeForStoreNamedProperty( |
| 932 LanguageMode language_mode) { |
| 933 switch (language_mode) { |
| 934 case SLOPPY: |
| 935 return Bytecode::kStaNamedPropertySloppy; |
| 936 case STRICT: |
| 937 return Bytecode::kStaNamedPropertyStrict; |
| 938 default: |
| 939 UNREACHABLE(); |
| 940 } |
| 941 return Bytecode::kIllegal; |
| 942 } |
| 943 |
| 944 // static |
| 945 Bytecode BytecodeArrayBuilder::BytecodeForStoreKeyedProperty( |
| 946 LanguageMode language_mode) { |
| 947 switch (language_mode) { |
| 948 case SLOPPY: |
| 949 return Bytecode::kStaKeyedPropertySloppy; |
| 950 case STRICT: |
| 951 return Bytecode::kStaKeyedPropertyStrict; |
| 952 default: |
| 953 UNREACHABLE(); |
| 954 } |
| 955 return Bytecode::kIllegal; |
| 956 } |
| 957 |
| 958 // static |
| 959 Bytecode BytecodeArrayBuilder::BytecodeForLoadGlobal(TypeofMode typeof_mode) { |
| 960 return typeof_mode == INSIDE_TYPEOF ? Bytecode::kLdaGlobalInsideTypeof |
| 961 : Bytecode::kLdaGlobal; |
| 962 } |
| 963 |
| 964 // static |
| 965 Bytecode BytecodeArrayBuilder::BytecodeForStoreGlobal( |
| 966 LanguageMode language_mode) { |
| 967 switch (language_mode) { |
| 968 case SLOPPY: |
| 969 return Bytecode::kStaGlobalSloppy; |
| 970 case STRICT: |
| 971 return Bytecode::kStaGlobalStrict; |
| 972 default: |
| 973 UNREACHABLE(); |
| 974 } |
| 975 return Bytecode::kIllegal; |
| 976 } |
| 977 |
| 978 // static |
| 979 Bytecode BytecodeArrayBuilder::BytecodeForStoreLookupSlot( |
| 980 LanguageMode language_mode) { |
| 981 switch (language_mode) { |
| 982 case SLOPPY: |
| 983 return Bytecode::kStaLookupSlotSloppy; |
| 984 case STRICT: |
| 985 return Bytecode::kStaLookupSlotStrict; |
| 986 default: |
| 987 UNREACHABLE(); |
| 988 } |
| 989 return Bytecode::kIllegal; |
| 990 } |
| 991 |
| 992 // static |
| 993 Bytecode BytecodeArrayBuilder::BytecodeForCreateArguments( |
| 994 CreateArgumentsType type) { |
| 995 switch (type) { |
| 996 case CreateArgumentsType::kMappedArguments: |
| 997 return Bytecode::kCreateMappedArguments; |
| 998 case CreateArgumentsType::kUnmappedArguments: |
| 999 return Bytecode::kCreateUnmappedArguments; |
| 1000 case CreateArgumentsType::kRestParameter: |
| 1001 return Bytecode::kCreateRestParameter; |
| 1002 } |
| 1003 UNREACHABLE(); |
| 1004 return Bytecode::kIllegal; |
| 1005 } |
| 1006 |
| 1007 // static |
| 1008 Bytecode BytecodeArrayBuilder::BytecodeForDelete(LanguageMode language_mode) { |
| 1009 switch (language_mode) { |
| 1010 case SLOPPY: |
| 1011 return Bytecode::kDeletePropertySloppy; |
| 1012 case STRICT: |
| 1013 return Bytecode::kDeletePropertyStrict; |
| 1014 default: |
| 1015 UNREACHABLE(); |
| 1016 } |
| 1017 return Bytecode::kIllegal; |
| 1018 } |
| 1019 |
| 1020 // static |
| 1021 Bytecode BytecodeArrayBuilder::BytecodeForCall(TailCallMode tail_call_mode) { |
| 1022 switch (tail_call_mode) { |
| 1023 case TailCallMode::kDisallow: |
| 1024 return Bytecode::kCall; |
| 1025 case TailCallMode::kAllow: |
| 1026 return Bytecode::kTailCall; |
| 1027 default: |
| 1028 UNREACHABLE(); |
| 1029 } |
| 1030 return Bytecode::kIllegal; |
| 1031 } |
| 1032 |
| 941 } // namespace interpreter | 1033 } // namespace interpreter |
| 942 } // namespace internal | 1034 } // namespace internal |
| 943 } // namespace v8 | 1035 } // namespace v8 |
| OLD | NEW |