| 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, fixed_register_count(), | 83 return pipeline_->ToBytecodeArray(isolate, |
| 84 fixed_and_temporary_register_count(), |
| 84 parameter_count(), handler_table); | 85 parameter_count(), handler_table); |
| 85 } | 86 } |
| 86 | 87 |
| 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 | |
| 113 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | 88 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, |
| 114 uint32_t operand1, uint32_t operand2, | 89 uint32_t operand1, uint32_t operand2, |
| 115 uint32_t operand3) { | 90 uint32_t operand3) { |
| 116 DCHECK(OperandsAreValid(bytecode, 4, operand0, operand1, operand2, operand3)); | 91 DCHECK(OperandsAreValid(bytecode, 4, operand0, operand1, operand2, operand3)); |
| 117 BytecodeNode node(bytecode, operand0, operand1, operand2, operand3); | 92 BytecodeNode node(bytecode, operand0, operand1, operand2, operand3, |
| 118 AttachSourceInfo(&node); | 93 &latest_source_info_); |
| 119 pipeline()->Write(&node); | 94 pipeline()->Write(&node); |
| 120 } | 95 } |
| 121 | 96 |
| 122 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | 97 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, |
| 123 uint32_t operand1, uint32_t operand2) { | 98 uint32_t operand1, uint32_t operand2) { |
| 124 DCHECK(OperandsAreValid(bytecode, 3, operand0, operand1, operand2)); | 99 DCHECK(OperandsAreValid(bytecode, 3, operand0, operand1, operand2)); |
| 125 BytecodeNode node(bytecode, operand0, operand1, operand2); | 100 BytecodeNode node(bytecode, operand0, operand1, operand2, |
| 126 AttachSourceInfo(&node); | 101 &latest_source_info_); |
| 127 pipeline()->Write(&node); | 102 pipeline()->Write(&node); |
| 128 } | 103 } |
| 129 | 104 |
| 130 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | 105 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, |
| 131 uint32_t operand1) { | 106 uint32_t operand1) { |
| 132 DCHECK(OperandsAreValid(bytecode, 2, operand0, operand1)); | 107 DCHECK(OperandsAreValid(bytecode, 2, operand0, operand1)); |
| 133 BytecodeNode node(bytecode, operand0, operand1); | 108 BytecodeNode node(bytecode, operand0, operand1, &latest_source_info_); |
| 134 AttachSourceInfo(&node); | |
| 135 pipeline()->Write(&node); | 109 pipeline()->Write(&node); |
| 136 } | 110 } |
| 137 | 111 |
| 138 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0) { | 112 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0) { |
| 139 DCHECK(OperandsAreValid(bytecode, 1, operand0)); | 113 DCHECK(OperandsAreValid(bytecode, 1, operand0)); |
| 140 BytecodeNode node(bytecode, operand0); | 114 BytecodeNode node(bytecode, operand0, &latest_source_info_); |
| 141 AttachSourceInfo(&node); | |
| 142 pipeline()->Write(&node); | 115 pipeline()->Write(&node); |
| 143 } | 116 } |
| 144 | 117 |
| 145 void BytecodeArrayBuilder::Output(Bytecode bytecode) { | 118 void BytecodeArrayBuilder::Output(Bytecode bytecode) { |
| 146 DCHECK(OperandsAreValid(bytecode, 0)); | 119 DCHECK(OperandsAreValid(bytecode, 0)); |
| 147 BytecodeNode node(bytecode); | 120 BytecodeNode node(bytecode, &latest_source_info_); |
| 148 AttachSourceInfo(&node); | |
| 149 pipeline()->Write(&node); | 121 pipeline()->Write(&node); |
| 150 } | 122 } |
| 151 | 123 |
| 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 |
| 152 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, | 137 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, |
| 153 Register reg, | 138 Register reg, |
| 154 int feedback_slot) { | 139 int feedback_slot) { |
| 155 Output(BytecodeForBinaryOperation(op), RegisterOperand(reg), | 140 switch (op) { |
| 156 UnsignedOperand(feedback_slot)); | 141 case Token::Value::ADD: |
| 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 } |
| 157 return *this; | 188 return *this; |
| 158 } | 189 } |
| 159 | 190 |
| 160 BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op, | 191 BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op, |
| 161 int feedback_slot) { | 192 int feedback_slot) { |
| 162 Output(BytecodeForCountOperation(op), UnsignedOperand(feedback_slot)); | 193 if (op == Token::Value::ADD) { |
| 194 Output(Bytecode::kInc, UnsignedOperand(feedback_slot)); |
| 195 } else { |
| 196 DCHECK_EQ(op, Token::Value::SUB); |
| 197 Output(Bytecode::kDec, UnsignedOperand(feedback_slot)); |
| 198 } |
| 163 return *this; | 199 return *this; |
| 164 } | 200 } |
| 165 | 201 |
| 166 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() { | 202 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() { |
| 167 Output(Bytecode::kToBooleanLogicalNot); | 203 Output(Bytecode::kToBooleanLogicalNot); |
| 168 return *this; | 204 return *this; |
| 169 } | 205 } |
| 170 | 206 |
| 171 | |
| 172 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() { | 207 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() { |
| 173 Output(Bytecode::kTypeOf); | 208 Output(Bytecode::kTypeOf); |
| 174 return *this; | 209 return *this; |
| 175 } | 210 } |
| 176 | 211 |
| 177 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation( | 212 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation( |
| 178 Token::Value op, Register reg, int feedback_slot) { | 213 Token::Value op, Register reg, int feedback_slot) { |
| 179 if (op == Token::INSTANCEOF || op == Token::IN) { | 214 switch (op) { |
| 180 Output(BytecodeForCompareOperation(op), RegisterOperand(reg)); | 215 case Token::Value::EQ: |
| 181 } else { | 216 Output(Bytecode::kTestEqual, RegisterOperand(reg), |
| 182 Output(BytecodeForCompareOperation(op), RegisterOperand(reg), | 217 UnsignedOperand(feedback_slot)); |
| 183 UnsignedOperand(feedback_slot)); | 218 break; |
| 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(); |
| 184 } | 251 } |
| 185 return *this; | 252 return *this; |
| 186 } | 253 } |
| 187 | 254 |
| 188 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry( | 255 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry( |
| 189 size_t entry) { | 256 size_t entry) { |
| 190 Output(Bytecode::kLdaConstant, UnsignedOperand(entry)); | 257 Output(Bytecode::kLdaConstant, UnsignedOperand(entry)); |
| 191 return *this; | 258 return *this; |
| 192 } | 259 } |
| 193 | 260 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 | 314 |
| 248 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, | 315 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, |
| 249 Register to) { | 316 Register to) { |
| 250 DCHECK(from != to); | 317 DCHECK(from != to); |
| 251 Output(Bytecode::kMov, RegisterOperand(from), RegisterOperand(to)); | 318 Output(Bytecode::kMov, RegisterOperand(from), RegisterOperand(to)); |
| 252 return *this; | 319 return *this; |
| 253 } | 320 } |
| 254 | 321 |
| 255 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(int feedback_slot, | 322 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(int feedback_slot, |
| 256 TypeofMode typeof_mode) { | 323 TypeofMode typeof_mode) { |
| 257 // TODO(rmcilroy): Potentially store typeof information in an | 324 if (typeof_mode == INSIDE_TYPEOF) { |
| 258 // operand rather than having extra bytecodes. | 325 Output(Bytecode::kLdaGlobalInsideTypeof, feedback_slot); |
| 259 Bytecode bytecode = BytecodeForLoadGlobal(typeof_mode); | 326 } else { |
| 260 Output(bytecode, UnsignedOperand(feedback_slot)); | 327 DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF); |
| 328 Output(Bytecode::kLdaGlobal, UnsignedOperand(feedback_slot)); |
| 329 } |
| 261 return *this; | 330 return *this; |
| 262 } | 331 } |
| 263 | 332 |
| 264 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal( | 333 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal( |
| 265 const Handle<String> name, int feedback_slot, LanguageMode language_mode) { | 334 const Handle<String> name, int feedback_slot, LanguageMode language_mode) { |
| 266 Bytecode bytecode = BytecodeForStoreGlobal(language_mode); | |
| 267 size_t name_index = GetConstantPoolEntry(name); | 335 size_t name_index = GetConstantPoolEntry(name); |
| 268 Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); | 336 if (language_mode == SLOPPY) { |
| 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 } |
| 269 return *this; | 344 return *this; |
| 270 } | 345 } |
| 271 | 346 |
| 272 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context, | 347 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context, |
| 273 int slot_index, | 348 int slot_index, |
| 274 int depth) { | 349 int depth) { |
| 275 Output(Bytecode::kLdaContextSlot, RegisterOperand(context), | 350 Output(Bytecode::kLdaContextSlot, RegisterOperand(context), |
| 276 UnsignedOperand(slot_index), UnsignedOperand(depth)); | 351 UnsignedOperand(slot_index), UnsignedOperand(depth)); |
| 277 return *this; | 352 return *this; |
| 278 } | 353 } |
| 279 | 354 |
| 280 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context, | 355 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context, |
| 281 int slot_index, | 356 int slot_index, |
| 282 int depth) { | 357 int depth) { |
| 283 Output(Bytecode::kStaContextSlot, RegisterOperand(context), | 358 Output(Bytecode::kStaContextSlot, RegisterOperand(context), |
| 284 UnsignedOperand(slot_index), UnsignedOperand(depth)); | 359 UnsignedOperand(slot_index), UnsignedOperand(depth)); |
| 285 return *this; | 360 return *this; |
| 286 } | 361 } |
| 287 | 362 |
| 288 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot( | 363 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot( |
| 289 const Handle<String> name, TypeofMode typeof_mode) { | 364 const Handle<String> name, TypeofMode typeof_mode) { |
| 290 Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF) | |
| 291 ? Bytecode::kLdaLookupSlotInsideTypeof | |
| 292 : Bytecode::kLdaLookupSlot; | |
| 293 size_t name_index = GetConstantPoolEntry(name); | 365 size_t name_index = GetConstantPoolEntry(name); |
| 294 Output(bytecode, UnsignedOperand(name_index)); | 366 if (typeof_mode == INSIDE_TYPEOF) { |
| 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 } |
| 295 return *this; | 372 return *this; |
| 296 } | 373 } |
| 297 | 374 |
| 298 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupContextSlot( | 375 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupContextSlot( |
| 299 const Handle<String> name, TypeofMode typeof_mode, int slot_index, | 376 const Handle<String> name, TypeofMode typeof_mode, int slot_index, |
| 300 int depth) { | 377 int depth) { |
| 301 Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF) | 378 Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF) |
| 302 ? Bytecode::kLdaLookupContextSlotInsideTypeof | 379 ? Bytecode::kLdaLookupContextSlotInsideTypeof |
| 303 : Bytecode::kLdaLookupContextSlot; | 380 : Bytecode::kLdaLookupContextSlot; |
| 304 size_t name_index = GetConstantPoolEntry(name); | 381 size_t name_index = GetConstantPoolEntry(name); |
| 305 Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(slot_index), | 382 Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(slot_index), |
| 306 UnsignedOperand(depth)); | 383 UnsignedOperand(depth)); |
| 307 return *this; | 384 return *this; |
| 308 } | 385 } |
| 309 | 386 |
| 310 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupGlobalSlot( | 387 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupGlobalSlot( |
| 311 const Handle<String> name, TypeofMode typeof_mode, int feedback_slot, | 388 const Handle<String> name, TypeofMode typeof_mode, int feedback_slot, |
| 312 int depth) { | 389 int depth) { |
| 313 Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF) | 390 Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF) |
| 314 ? Bytecode::kLdaLookupGlobalSlotInsideTypeof | 391 ? Bytecode::kLdaLookupGlobalSlotInsideTypeof |
| 315 : Bytecode::kLdaLookupGlobalSlot; | 392 : Bytecode::kLdaLookupGlobalSlot; |
| 316 size_t name_index = GetConstantPoolEntry(name); | 393 size_t name_index = GetConstantPoolEntry(name); |
| 317 Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(feedback_slot), | 394 Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(feedback_slot), |
| 318 UnsignedOperand(depth)); | 395 UnsignedOperand(depth)); |
| 319 return *this; | 396 return *this; |
| 320 } | 397 } |
| 321 | 398 |
| 322 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot( | 399 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot( |
| 323 const Handle<String> name, LanguageMode language_mode) { | 400 const Handle<String> name, LanguageMode language_mode) { |
| 324 Bytecode bytecode = BytecodeForStoreLookupSlot(language_mode); | |
| 325 size_t name_index = GetConstantPoolEntry(name); | 401 size_t name_index = GetConstantPoolEntry(name); |
| 326 Output(bytecode, UnsignedOperand(name_index)); | 402 if (language_mode == SLOPPY) { |
| 403 Output(Bytecode::kStaLookupSlotSloppy, UnsignedOperand(name_index)); |
| 404 } else { |
| 405 DCHECK_EQ(language_mode, STRICT); |
| 406 Output(Bytecode::kStaLookupSlotStrict, UnsignedOperand(name_index)); |
| 407 } |
| 327 return *this; | 408 return *this; |
| 328 } | 409 } |
| 329 | 410 |
| 330 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( | 411 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( |
| 331 Register object, const Handle<Name> name, int feedback_slot) { | 412 Register object, const Handle<Name> name, int feedback_slot) { |
| 332 size_t name_index = GetConstantPoolEntry(name); | 413 size_t name_index = GetConstantPoolEntry(name); |
| 333 Output(Bytecode::kLdaNamedProperty, RegisterOperand(object), | 414 Output(Bytecode::kLdaNamedProperty, RegisterOperand(object), |
| 334 UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); | 415 UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); |
| 335 return *this; | 416 return *this; |
| 336 } | 417 } |
| 337 | 418 |
| 338 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( | 419 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( |
| 339 Register object, int feedback_slot) { | 420 Register object, int feedback_slot) { |
| 340 Output(Bytecode::kLdaKeyedProperty, RegisterOperand(object), | 421 Output(Bytecode::kLdaKeyedProperty, RegisterOperand(object), |
| 341 UnsignedOperand(feedback_slot)); | 422 UnsignedOperand(feedback_slot)); |
| 342 return *this; | 423 return *this; |
| 343 } | 424 } |
| 344 | 425 |
| 345 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( | 426 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( |
| 346 Register object, const Handle<Name> name, int feedback_slot, | 427 Register object, const Handle<Name> name, int feedback_slot, |
| 347 LanguageMode language_mode) { | 428 LanguageMode language_mode) { |
| 348 Bytecode bytecode = BytecodeForStoreNamedProperty(language_mode); | |
| 349 size_t name_index = GetConstantPoolEntry(name); | 429 size_t name_index = GetConstantPoolEntry(name); |
| 350 Output(bytecode, RegisterOperand(object), UnsignedOperand(name_index), | 430 if (language_mode == SLOPPY) { |
| 351 UnsignedOperand(feedback_slot)); | 431 Output(Bytecode::kStaNamedPropertySloppy, RegisterOperand(object), |
| 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 } |
| 352 return *this; | 438 return *this; |
| 353 } | 439 } |
| 354 | 440 |
| 355 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( | 441 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( |
| 356 Register object, Register key, int feedback_slot, | 442 Register object, Register key, int feedback_slot, |
| 357 LanguageMode language_mode) { | 443 LanguageMode language_mode) { |
| 358 Bytecode bytecode = BytecodeForStoreKeyedProperty(language_mode); | 444 if (language_mode == SLOPPY) { |
| 359 Output(bytecode, RegisterOperand(object), RegisterOperand(key), | 445 Output(Bytecode::kStaKeyedPropertySloppy, RegisterOperand(object), |
| 360 UnsignedOperand(feedback_slot)); | 446 RegisterOperand(key), UnsignedOperand(feedback_slot)); |
| 447 } else { |
| 448 DCHECK_EQ(language_mode, STRICT); |
| 449 Output(Bytecode::kStaKeyedPropertyStrict, RegisterOperand(object), |
| 450 RegisterOperand(key), UnsignedOperand(feedback_slot)); |
| 451 } |
| 361 return *this; | 452 return *this; |
| 362 } | 453 } |
| 363 | 454 |
| 364 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(size_t entry, | 455 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(size_t entry, |
| 365 int flags) { | 456 int flags) { |
| 366 Output(Bytecode::kCreateClosure, UnsignedOperand(entry), | 457 Output(Bytecode::kCreateClosure, UnsignedOperand(entry), |
| 367 UnsignedOperand(flags)); | 458 UnsignedOperand(flags)); |
| 368 return *this; | 459 return *this; |
| 369 } | 460 } |
| 370 | 461 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 392 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext( | 483 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext( |
| 393 Register object, Handle<ScopeInfo> scope_info) { | 484 Register object, Handle<ScopeInfo> scope_info) { |
| 394 size_t scope_info_index = GetConstantPoolEntry(scope_info); | 485 size_t scope_info_index = GetConstantPoolEntry(scope_info); |
| 395 Output(Bytecode::kCreateWithContext, RegisterOperand(object), | 486 Output(Bytecode::kCreateWithContext, RegisterOperand(object), |
| 396 UnsignedOperand(scope_info_index)); | 487 UnsignedOperand(scope_info_index)); |
| 397 return *this; | 488 return *this; |
| 398 } | 489 } |
| 399 | 490 |
| 400 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments( | 491 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments( |
| 401 CreateArgumentsType type) { | 492 CreateArgumentsType type) { |
| 402 // TODO(rmcilroy): Consider passing the type as a bytecode operand rather | 493 switch (type) { |
| 403 // than having two different bytecodes once we have better support for | 494 case CreateArgumentsType::kMappedArguments: |
| 404 // branches in the InterpreterAssembler. | 495 Output(Bytecode::kCreateMappedArguments); |
| 405 Bytecode bytecode = BytecodeForCreateArguments(type); | 496 break; |
| 406 Output(bytecode); | 497 case CreateArgumentsType::kUnmappedArguments: |
| 498 Output(Bytecode::kCreateUnmappedArguments); |
| 499 break; |
| 500 case CreateArgumentsType::kRestParameter: |
| 501 Output(Bytecode::kCreateRestParameter); |
| 502 break; |
| 503 default: |
| 504 UNREACHABLE(); |
| 505 } |
| 407 return *this; | 506 return *this; |
| 408 } | 507 } |
| 409 | 508 |
| 410 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral( | 509 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral( |
| 411 Handle<String> pattern, int literal_index, int flags) { | 510 Handle<String> pattern, int literal_index, int flags) { |
| 412 size_t pattern_entry = GetConstantPoolEntry(pattern); | 511 size_t pattern_entry = GetConstantPoolEntry(pattern); |
| 413 Output(Bytecode::kCreateRegExpLiteral, UnsignedOperand(pattern_entry), | 512 Output(Bytecode::kCreateRegExpLiteral, UnsignedOperand(pattern_entry), |
| 414 UnsignedOperand(literal_index), UnsignedOperand(flags)); | 513 UnsignedOperand(literal_index), UnsignedOperand(flags)); |
| 415 return *this; | 514 return *this; |
| 416 } | 515 } |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 return *this; | 568 return *this; |
| 470 } | 569 } |
| 471 | 570 |
| 472 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target, | 571 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target, |
| 473 BytecodeLabel* label) { | 572 BytecodeLabel* label) { |
| 474 pipeline_->BindLabel(target, label); | 573 pipeline_->BindLabel(target, label); |
| 475 LeaveBasicBlock(); | 574 LeaveBasicBlock(); |
| 476 return *this; | 575 return *this; |
| 477 } | 576 } |
| 478 | 577 |
| 479 BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(BytecodeNode* node, | |
| 480 BytecodeLabel* label) { | |
| 481 AttachSourceInfo(node); | |
| 482 pipeline_->WriteJump(node, label); | |
| 483 LeaveBasicBlock(); | |
| 484 return *this; | |
| 485 } | |
| 486 | |
| 487 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { | 578 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { |
| 488 BytecodeNode node(Bytecode::kJump, 0); | 579 OutputJump(Bytecode::kJump, label); |
| 489 return OutputJump(&node, label); | 580 return *this; |
| 490 } | 581 } |
| 491 | 582 |
| 492 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) { | 583 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) { |
| 493 // The peephole optimizer attempts to simplify JumpIfToBooleanTrue | 584 // The peephole optimizer attempts to simplify JumpIfToBooleanTrue |
| 494 // to JumpIfTrue. | 585 // to JumpIfTrue. |
| 495 BytecodeNode node(Bytecode::kJumpIfToBooleanTrue, 0); | 586 OutputJump(Bytecode::kJumpIfToBooleanTrue, label); |
| 496 return OutputJump(&node, label); | 587 return *this; |
| 497 } | 588 } |
| 498 | 589 |
| 499 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) { | 590 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) { |
| 500 // The peephole optimizer attempts to simplify JumpIfToBooleanFalse | 591 OutputJump(Bytecode::kJumpIfToBooleanFalse, label); |
| 501 // to JumpIfFalse. | 592 return *this; |
| 502 BytecodeNode node(Bytecode::kJumpIfToBooleanFalse, 0); | |
| 503 return OutputJump(&node, label); | |
| 504 } | 593 } |
| 505 | 594 |
| 506 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) { | 595 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) { |
| 507 BytecodeNode node(Bytecode::kJumpIfNull, 0); | 596 OutputJump(Bytecode::kJumpIfNull, label); |
| 508 return OutputJump(&node, label); | 597 return *this; |
| 509 } | 598 } |
| 510 | 599 |
| 511 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined( | 600 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined( |
| 512 BytecodeLabel* label) { | 601 BytecodeLabel* label) { |
| 513 BytecodeNode node(Bytecode::kJumpIfUndefined, 0); | 602 OutputJump(Bytecode::kJumpIfUndefined, label); |
| 514 return OutputJump(&node, label); | 603 return *this; |
| 515 } | 604 } |
| 516 | 605 |
| 517 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole( | 606 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole( |
| 518 BytecodeLabel* label) { | 607 BytecodeLabel* label) { |
| 519 BytecodeNode node(Bytecode::kJumpIfNotHole, 0); | 608 OutputJump(Bytecode::kJumpIfNotHole, label); |
| 520 return OutputJump(&node, label); | 609 return *this; |
| 521 } | 610 } |
| 522 | 611 |
| 523 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label, | 612 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label, |
| 524 int loop_depth) { | 613 int loop_depth) { |
| 525 BytecodeNode node(Bytecode::kJumpLoop, 0, UnsignedOperand(loop_depth)); | 614 OutputJump(Bytecode::kJumpLoop, UnsignedOperand(loop_depth), label); |
| 526 return OutputJump(&node, label); | 615 return *this; |
| 527 } | 616 } |
| 528 | 617 |
| 529 BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) { | 618 BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) { |
| 530 if (position != kNoSourcePosition) { | 619 if (position != kNoSourcePosition) { |
| 531 // We need to attach a non-breakable source position to a stack | 620 // We need to attach a non-breakable source position to a stack |
| 532 // check, so we simply add it as expression position. There can be | 621 // check, so we simply add it as expression position. There can be |
| 533 // a prior statement position from constructs like: | 622 // a prior statement position from constructs like: |
| 534 // | 623 // |
| 535 // do var x; while (false); | 624 // do var x; while (false); |
| 536 // | 625 // |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 637 Return(); | 726 Return(); |
| 638 } | 727 } |
| 639 DCHECK(return_seen_in_block_); | 728 DCHECK(return_seen_in_block_); |
| 640 } | 729 } |
| 641 | 730 |
| 642 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, | 731 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, |
| 643 Register receiver_args, | 732 Register receiver_args, |
| 644 size_t receiver_args_count, | 733 size_t receiver_args_count, |
| 645 int feedback_slot, | 734 int feedback_slot, |
| 646 TailCallMode tail_call_mode) { | 735 TailCallMode tail_call_mode) { |
| 647 Bytecode bytecode = BytecodeForCall(tail_call_mode); | 736 if (tail_call_mode == TailCallMode::kDisallow) { |
| 648 Output(bytecode, RegisterOperand(callable), RegisterOperand(receiver_args), | 737 Output(Bytecode::kCall, RegisterOperand(callable), |
| 649 UnsignedOperand(receiver_args_count), UnsignedOperand(feedback_slot)); | 738 RegisterOperand(receiver_args), UnsignedOperand(receiver_args_count), |
| 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 } |
| 650 return *this; | 746 return *this; |
| 651 } | 747 } |
| 652 | 748 |
| 653 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, | 749 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, |
| 654 Register first_arg, | 750 Register first_arg, |
| 655 size_t arg_count, | 751 size_t arg_count, |
| 656 int feedback_slot_id) { | 752 int feedback_slot_id) { |
| 657 if (!first_arg.is_valid()) { | 753 if (!first_arg.is_valid()) { |
| 658 DCHECK_EQ(0u, arg_count); | 754 DCHECK_EQ(0u, arg_count); |
| 659 first_arg = Register(0); | 755 first_arg = Register(0); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 702 | 798 |
| 703 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime( | 799 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime( |
| 704 int context_index, Register receiver_args, size_t receiver_args_count) { | 800 int context_index, Register receiver_args, size_t receiver_args_count) { |
| 705 Output(Bytecode::kCallJSRuntime, UnsignedOperand(context_index), | 801 Output(Bytecode::kCallJSRuntime, UnsignedOperand(context_index), |
| 706 RegisterOperand(receiver_args), UnsignedOperand(receiver_args_count)); | 802 RegisterOperand(receiver_args), UnsignedOperand(receiver_args_count)); |
| 707 return *this; | 803 return *this; |
| 708 } | 804 } |
| 709 | 805 |
| 710 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, | 806 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, |
| 711 LanguageMode language_mode) { | 807 LanguageMode language_mode) { |
| 712 Output(BytecodeForDelete(language_mode), RegisterOperand(object)); | 808 if (language_mode == SLOPPY) { |
| 809 Output(Bytecode::kDeletePropertySloppy, RegisterOperand(object)); |
| 810 } else { |
| 811 DCHECK_EQ(language_mode, STRICT); |
| 812 Output(Bytecode::kDeletePropertyStrict, RegisterOperand(object)); |
| 813 } |
| 713 return *this; | 814 return *this; |
| 714 } | 815 } |
| 715 | 816 |
| 716 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { | 817 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { |
| 717 return constant_array_builder()->Insert(object); | 818 return constant_array_builder()->Insert(object); |
| 718 } | 819 } |
| 719 | 820 |
| 720 size_t BytecodeArrayBuilder::AllocateConstantPoolEntry() { | 821 size_t BytecodeArrayBuilder::AllocateConstantPoolEntry() { |
| 721 return constant_array_builder()->AllocateEntry(); | 822 return constant_array_builder()->AllocateEntry(); |
| 722 } | 823 } |
| 723 | 824 |
| 724 void BytecodeArrayBuilder::InsertConstantPoolEntryAt(size_t entry, | 825 void BytecodeArrayBuilder::InsertConstantPoolEntryAt(size_t entry, |
| 725 Handle<Object> object) { | 826 Handle<Object> object) { |
| 726 constant_array_builder()->InsertAllocatedEntry(entry, object); | 827 constant_array_builder()->InsertAllocatedEntry(entry, object); |
| 727 } | 828 } |
| 728 | 829 |
| 729 void BytecodeArrayBuilder::SetReturnPosition() { | 830 void BytecodeArrayBuilder::SetReturnPosition() { |
| 730 if (return_position_ == kNoSourcePosition) return; | 831 if (return_position_ == kNoSourcePosition) return; |
| 731 latest_source_info_.MakeStatementPosition(return_position_); | 832 latest_source_info_.MakeStatementPosition(return_position_); |
| 732 } | 833 } |
| 733 | 834 |
| 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 | |
| 753 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { | 835 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { |
| 754 return temporary_register_allocator()->RegisterIsLive(reg); | 836 return temporary_register_allocator()->RegisterIsLive(reg); |
| 755 } | 837 } |
| 756 | 838 |
| 757 bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const { | 839 bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const { |
| 758 if (!reg.is_valid()) { | 840 if (!reg.is_valid()) { |
| 759 return false; | 841 return false; |
| 760 } | 842 } |
| 761 | 843 |
| 762 if (reg.is_current_context() || reg.is_function_closure() || | 844 if (reg.is_current_context() || reg.is_function_closure() || |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 806 } | 888 } |
| 807 break; | 889 break; |
| 808 case OperandType::kRuntimeId: | 890 case OperandType::kRuntimeId: |
| 809 if (Bytecodes::SizeForUnsignedOperand(operands[i]) > | 891 if (Bytecodes::SizeForUnsignedOperand(operands[i]) > |
| 810 OperandSize::kShort) { | 892 OperandSize::kShort) { |
| 811 return false; | 893 return false; |
| 812 } | 894 } |
| 813 break; | 895 break; |
| 814 case OperandType::kIdx: | 896 case OperandType::kIdx: |
| 815 // TODO(leszeks): Possibly split this up into constant pool indices and | 897 // TODO(leszeks): Possibly split this up into constant pool indices and |
| 816 // other indices, for checking | 898 // other indices, for checking. |
| 817 break; | 899 break; |
| 818 case OperandType::kUImm: | 900 case OperandType::kUImm: |
| 819 case OperandType::kImm: | 901 case OperandType::kImm: |
| 820 break; | 902 break; |
| 821 case OperandType::kMaybeReg: | 903 case OperandType::kMaybeReg: |
| 822 if (Register::FromOperand(operands[i]) == Register(0)) { | 904 if (Register::FromOperand(operands[i]) == Register(0)) { |
| 823 break; | 905 break; |
| 824 } | 906 } |
| 825 // Fall-through to kReg case. | 907 // Fall-through to kReg case. |
| 826 case OperandType::kReg: | 908 case OperandType::kReg: |
| (...skipping 22 matching lines...) Expand all Loading... |
| 849 return false; | 931 return false; |
| 850 } | 932 } |
| 851 break; | 933 break; |
| 852 } | 934 } |
| 853 } | 935 } |
| 854 } | 936 } |
| 855 | 937 |
| 856 return true; | 938 return true; |
| 857 } | 939 } |
| 858 | 940 |
| 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 | |
| 1033 } // namespace interpreter | 941 } // namespace interpreter |
| 1034 } // namespace internal | 942 } // namespace internal |
| 1035 } // namespace v8 | 943 } // namespace v8 |
| OLD | NEW |