| 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 namespace v8 { | 7 namespace v8 { |
| 8 namespace internal { | 8 namespace internal { |
| 9 namespace interpreter { | 9 namespace interpreter { |
| 10 | 10 |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 Output(Bytecode::kLdaSmi8, static_cast<uint8_t>(raw_smi)); | 154 Output(Bytecode::kLdaSmi8, static_cast<uint8_t>(raw_smi)); |
| 155 } else { | 155 } else { |
| 156 LoadLiteral(Handle<Object>(smi, isolate_)); | 156 LoadLiteral(Handle<Object>(smi, isolate_)); |
| 157 } | 157 } |
| 158 return *this; | 158 return *this; |
| 159 } | 159 } |
| 160 | 160 |
| 161 | 161 |
| 162 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) { | 162 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) { |
| 163 size_t entry = GetConstantPoolEntry(object); | 163 size_t entry = GetConstantPoolEntry(object); |
| 164 if (FitsInIdxOperand(entry)) { | 164 if (FitsInIdx8Operand(entry)) { |
| 165 Output(Bytecode::kLdaConstant, static_cast<uint8_t>(entry)); | 165 Output(Bytecode::kLdaConstant, static_cast<uint8_t>(entry)); |
| 166 } else { | 166 } else { |
| 167 UNIMPLEMENTED(); | 167 UNIMPLEMENTED(); |
| 168 } | 168 } |
| 169 return *this; | 169 return *this; |
| 170 } | 170 } |
| 171 | 171 |
| 172 | 172 |
| 173 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() { | 173 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() { |
| 174 Output(Bytecode::kLdaUndefined); | 174 Output(Bytecode::kLdaUndefined); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 | 209 |
| 210 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister( | 210 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister( |
| 211 Register reg) { | 211 Register reg) { |
| 212 Output(Bytecode::kStar, reg.ToOperand()); | 212 Output(Bytecode::kStar, reg.ToOperand()); |
| 213 return *this; | 213 return *this; |
| 214 } | 214 } |
| 215 | 215 |
| 216 | 216 |
| 217 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(int slot_index) { | 217 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(int slot_index) { |
| 218 DCHECK(slot_index >= 0); | 218 DCHECK(slot_index >= 0); |
| 219 if (FitsInIdxOperand(slot_index)) { | 219 if (FitsInIdx8Operand(slot_index)) { |
| 220 Output(Bytecode::kLdaGlobal, static_cast<uint8_t>(slot_index)); | 220 Output(Bytecode::kLdaGlobal, static_cast<uint8_t>(slot_index)); |
| 221 } else { | 221 } else { |
| 222 UNIMPLEMENTED(); | 222 UNIMPLEMENTED(); |
| 223 } | 223 } |
| 224 return *this; | 224 return *this; |
| 225 } | 225 } |
| 226 | 226 |
| 227 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( | 227 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( |
| 228 Register object, int feedback_slot, LanguageMode language_mode) { | 228 Register object, int feedback_slot, LanguageMode language_mode) { |
| 229 if (!is_sloppy(language_mode)) { | 229 if (!is_sloppy(language_mode)) { |
| 230 UNIMPLEMENTED(); | 230 UNIMPLEMENTED(); |
| 231 } | 231 } |
| 232 | 232 |
| 233 if (FitsInIdxOperand(feedback_slot)) { | 233 if (FitsInIdx8Operand(feedback_slot)) { |
| 234 Output(Bytecode::kLoadIC, object.ToOperand(), | 234 Output(Bytecode::kLoadIC, object.ToOperand(), |
| 235 static_cast<uint8_t>(feedback_slot)); | 235 static_cast<uint8_t>(feedback_slot)); |
| 236 } else { | 236 } else { |
| 237 UNIMPLEMENTED(); | 237 UNIMPLEMENTED(); |
| 238 } | 238 } |
| 239 return *this; | 239 return *this; |
| 240 } | 240 } |
| 241 | 241 |
| 242 | 242 |
| 243 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( | 243 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( |
| 244 Register object, int feedback_slot, LanguageMode language_mode) { | 244 Register object, int feedback_slot, LanguageMode language_mode) { |
| 245 if (!is_sloppy(language_mode)) { | 245 if (!is_sloppy(language_mode)) { |
| 246 UNIMPLEMENTED(); | 246 UNIMPLEMENTED(); |
| 247 } | 247 } |
| 248 | 248 |
| 249 if (FitsInIdxOperand(feedback_slot)) { | 249 if (FitsInIdx8Operand(feedback_slot)) { |
| 250 Output(Bytecode::kKeyedLoadIC, object.ToOperand(), | 250 Output(Bytecode::kKeyedLoadIC, object.ToOperand(), |
| 251 static_cast<uint8_t>(feedback_slot)); | 251 static_cast<uint8_t>(feedback_slot)); |
| 252 } else { | 252 } else { |
| 253 UNIMPLEMENTED(); | 253 UNIMPLEMENTED(); |
| 254 } | 254 } |
| 255 return *this; | 255 return *this; |
| 256 } | 256 } |
| 257 | 257 |
| 258 | 258 |
| 259 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( | 259 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( |
| 260 Register object, Register name, int feedback_slot, | 260 Register object, Register name, int feedback_slot, |
| 261 LanguageMode language_mode) { | 261 LanguageMode language_mode) { |
| 262 if (!is_sloppy(language_mode)) { | 262 if (!is_sloppy(language_mode)) { |
| 263 UNIMPLEMENTED(); | 263 UNIMPLEMENTED(); |
| 264 } | 264 } |
| 265 | 265 |
| 266 if (FitsInIdxOperand(feedback_slot)) { | 266 if (FitsInIdx8Operand(feedback_slot)) { |
| 267 Output(Bytecode::kStoreIC, object.ToOperand(), name.ToOperand(), | 267 Output(Bytecode::kStoreIC, object.ToOperand(), name.ToOperand(), |
| 268 static_cast<uint8_t>(feedback_slot)); | 268 static_cast<uint8_t>(feedback_slot)); |
| 269 } else { | 269 } else { |
| 270 UNIMPLEMENTED(); | 270 UNIMPLEMENTED(); |
| 271 } | 271 } |
| 272 return *this; | 272 return *this; |
| 273 } | 273 } |
| 274 | 274 |
| 275 | 275 |
| 276 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( | 276 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( |
| 277 Register object, Register key, int feedback_slot, | 277 Register object, Register key, int feedback_slot, |
| 278 LanguageMode language_mode) { | 278 LanguageMode language_mode) { |
| 279 if (!is_sloppy(language_mode)) { | 279 if (!is_sloppy(language_mode)) { |
| 280 UNIMPLEMENTED(); | 280 UNIMPLEMENTED(); |
| 281 } | 281 } |
| 282 | 282 |
| 283 if (FitsInIdxOperand(feedback_slot)) { | 283 if (FitsInIdx8Operand(feedback_slot)) { |
| 284 Output(Bytecode::kKeyedStoreIC, object.ToOperand(), key.ToOperand(), | 284 Output(Bytecode::kKeyedStoreIC, object.ToOperand(), key.ToOperand(), |
| 285 static_cast<uint8_t>(feedback_slot)); | 285 static_cast<uint8_t>(feedback_slot)); |
| 286 } else { | 286 } else { |
| 287 UNIMPLEMENTED(); | 287 UNIMPLEMENTED(); |
| 288 } | 288 } |
| 289 return *this; | 289 return *this; |
| 290 } | 290 } |
| 291 | 291 |
| 292 | 292 |
| 293 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToBoolean() { | 293 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToBoolean() { |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 DCHECK_EQ(Bytecodes::Size(jump_bytecode), 2); | 369 DCHECK_EQ(Bytecodes::Size(jump_bytecode), 2); |
| 370 DCHECK_NE(delta, 0); | 370 DCHECK_NE(delta, 0); |
| 371 | 371 |
| 372 if (FitsInImm8Operand(delta)) { | 372 if (FitsInImm8Operand(delta)) { |
| 373 // Just update the operand | 373 // Just update the operand |
| 374 jump_location++; | 374 jump_location++; |
| 375 *jump_location = static_cast<uint8_t>(delta); | 375 *jump_location = static_cast<uint8_t>(delta); |
| 376 } else { | 376 } else { |
| 377 // Update the jump type and operand | 377 // Update the jump type and operand |
| 378 size_t entry = GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate())); | 378 size_t entry = GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate())); |
| 379 if (FitsInIdxOperand(entry)) { | 379 if (FitsInIdx8Operand(entry)) { |
| 380 jump_bytecode = GetJumpWithConstantOperand(jump_bytecode); | 380 jump_bytecode = GetJumpWithConstantOperand(jump_bytecode); |
| 381 *jump_location++ = Bytecodes::ToByte(jump_bytecode); | 381 *jump_location++ = Bytecodes::ToByte(jump_bytecode); |
| 382 *jump_location = static_cast<uint8_t>(entry); | 382 *jump_location = static_cast<uint8_t>(entry); |
| 383 } else { | 383 } else { |
| 384 // TODO(oth): OutputJump should reserve a constant pool entry | 384 // TODO(oth): OutputJump should reserve a constant pool entry |
| 385 // when jump is written. The reservation should be used here if | 385 // when jump is written. The reservation should be used here if |
| 386 // needed, or cancelled if not. This is due to the patch needing | 386 // needed, or cancelled if not. This is due to the patch needing |
| 387 // to match the size of the code it's replacing. In future, | 387 // to match the size of the code it's replacing. In future, |
| 388 // there will probably be a jump with 32-bit operand for cases | 388 // there will probably be a jump with 32-bit operand for cases |
| 389 // when constant pool is full, but that needs to be emitted in | 389 // when constant pool is full, but that needs to be emitted in |
| (...skipping 17 matching lines...) Expand all Loading... |
| 407 // Label has not yet been bound so this is a forward reference | 407 // Label has not yet been bound so this is a forward reference |
| 408 // that will be patched when the label is bound. | 408 // that will be patched when the label is bound. |
| 409 label->set_referrer(bytecodes()->size()); | 409 label->set_referrer(bytecodes()->size()); |
| 410 delta = 0; | 410 delta = 0; |
| 411 } | 411 } |
| 412 | 412 |
| 413 if (FitsInImm8Operand(delta)) { | 413 if (FitsInImm8Operand(delta)) { |
| 414 Output(jump_bytecode, static_cast<uint8_t>(delta)); | 414 Output(jump_bytecode, static_cast<uint8_t>(delta)); |
| 415 } else { | 415 } else { |
| 416 size_t entry = GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate())); | 416 size_t entry = GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate())); |
| 417 if (FitsInIdxOperand(entry)) { | 417 if (FitsInIdx8Operand(entry)) { |
| 418 Output(GetJumpWithConstantOperand(jump_bytecode), | 418 Output(GetJumpWithConstantOperand(jump_bytecode), |
| 419 static_cast<uint8_t>(entry)); | 419 static_cast<uint8_t>(entry)); |
| 420 } else { | 420 } else { |
| 421 UNIMPLEMENTED(); | 421 UNIMPLEMENTED(); |
| 422 } | 422 } |
| 423 } | 423 } |
| 424 return *this; | 424 return *this; |
| 425 } | 425 } |
| 426 | 426 |
| 427 | 427 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 460 void BytecodeArrayBuilder::EnsureReturn() { | 460 void BytecodeArrayBuilder::EnsureReturn() { |
| 461 if (!return_seen_in_block_) { | 461 if (!return_seen_in_block_) { |
| 462 LoadUndefined(); | 462 LoadUndefined(); |
| 463 Return(); | 463 Return(); |
| 464 } | 464 } |
| 465 } | 465 } |
| 466 | 466 |
| 467 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, | 467 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, |
| 468 Register receiver, | 468 Register receiver, |
| 469 size_t arg_count) { | 469 size_t arg_count) { |
| 470 if (FitsInIdxOperand(arg_count)) { | 470 if (FitsInIdx8Operand(arg_count)) { |
| 471 Output(Bytecode::kCall, callable.ToOperand(), receiver.ToOperand(), | 471 Output(Bytecode::kCall, callable.ToOperand(), receiver.ToOperand(), |
| 472 static_cast<uint8_t>(arg_count)); | 472 static_cast<uint8_t>(arg_count)); |
| 473 } else { | 473 } else { |
| 474 UNIMPLEMENTED(); | 474 UNIMPLEMENTED(); |
| 475 } | 475 } |
| 476 return *this; | 476 return *this; |
| 477 } | 477 } |
| 478 | 478 |
| 479 | 479 |
| 480 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( |
| 481 Runtime::FunctionId function_id, Register first_arg, size_t arg_count) { |
| 482 DCHECK(FitsInIdx16Operand(function_id)); |
| 483 DCHECK(FitsInIdx8Operand(arg_count)); |
| 484 Output(Bytecode::kCallRuntime, static_cast<uint16_t>(function_id), |
| 485 first_arg.ToOperand(), static_cast<uint8_t>(arg_count)); |
| 486 return *this; |
| 487 } |
| 488 |
| 489 |
| 480 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { | 490 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { |
| 481 // These constants shouldn't be added to the constant pool, the should use | 491 // These constants shouldn't be added to the constant pool, the should use |
| 482 // specialzed bytecodes instead. | 492 // specialzed bytecodes instead. |
| 483 DCHECK(!object.is_identical_to(isolate_->factory()->undefined_value())); | 493 DCHECK(!object.is_identical_to(isolate_->factory()->undefined_value())); |
| 484 DCHECK(!object.is_identical_to(isolate_->factory()->null_value())); | 494 DCHECK(!object.is_identical_to(isolate_->factory()->null_value())); |
| 485 DCHECK(!object.is_identical_to(isolate_->factory()->the_hole_value())); | 495 DCHECK(!object.is_identical_to(isolate_->factory()->the_hole_value())); |
| 486 DCHECK(!object.is_identical_to(isolate_->factory()->true_value())); | 496 DCHECK(!object.is_identical_to(isolate_->factory()->true_value())); |
| 487 DCHECK(!object.is_identical_to(isolate_->factory()->false_value())); | 497 DCHECK(!object.is_identical_to(isolate_->factory()->false_value())); |
| 488 | 498 |
| 489 size_t* entry = constants_map_.Find(object); | 499 size_t* entry = constants_map_.Find(object); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 case Token::Value::IN: | 600 case Token::Value::IN: |
| 591 return Bytecode::kTestIn; | 601 return Bytecode::kTestIn; |
| 592 default: | 602 default: |
| 593 UNREACHABLE(); | 603 UNREACHABLE(); |
| 594 return static_cast<Bytecode>(-1); | 604 return static_cast<Bytecode>(-1); |
| 595 } | 605 } |
| 596 } | 606 } |
| 597 | 607 |
| 598 | 608 |
| 599 // static | 609 // static |
| 600 bool BytecodeArrayBuilder::FitsInIdxOperand(int value) { | 610 bool BytecodeArrayBuilder::FitsInIdx8Operand(int value) { |
| 601 return kMinUInt8 <= value && value <= kMaxUInt8; | 611 return kMinUInt8 <= value && value <= kMaxUInt8; |
| 602 } | 612 } |
| 603 | 613 |
| 604 | 614 |
| 605 // static | 615 // static |
| 606 bool BytecodeArrayBuilder::FitsInIdxOperand(size_t value) { | 616 bool BytecodeArrayBuilder::FitsInIdx8Operand(size_t value) { |
| 607 return value <= static_cast<size_t>(kMaxUInt8); | 617 return value <= static_cast<size_t>(kMaxUInt8); |
| 608 } | 618 } |
| 609 | 619 |
| 610 | 620 |
| 611 // static | 621 // static |
| 612 bool BytecodeArrayBuilder::FitsInImm8Operand(int value) { | 622 bool BytecodeArrayBuilder::FitsInImm8Operand(int value) { |
| 613 return kMinInt8 <= value && value < kMaxInt8; | 623 return kMinInt8 <= value && value < kMaxInt8; |
| 614 } | 624 } |
| 615 | 625 |
| 616 | 626 |
| 627 // static |
| 628 bool BytecodeArrayBuilder::FitsInIdx16Operand(int value) { |
| 629 return kMinUInt16 <= value && value <= kMaxUInt16; |
| 630 } |
| 631 |
| 632 |
| 617 TemporaryRegisterScope::TemporaryRegisterScope(BytecodeArrayBuilder* builder) | 633 TemporaryRegisterScope::TemporaryRegisterScope(BytecodeArrayBuilder* builder) |
| 618 : builder_(builder), count_(0), last_register_index_(-1) {} | 634 : builder_(builder), count_(0), last_register_index_(-1) {} |
| 619 | 635 |
| 620 | 636 |
| 621 TemporaryRegisterScope::~TemporaryRegisterScope() { | 637 TemporaryRegisterScope::~TemporaryRegisterScope() { |
| 622 while (count_-- != 0) { | 638 while (count_-- != 0) { |
| 623 builder_->ReturnTemporaryRegister(last_register_index_--); | 639 builder_->ReturnTemporaryRegister(last_register_index_--); |
| 624 } | 640 } |
| 625 } | 641 } |
| 626 | 642 |
| 627 | 643 |
| 628 Register TemporaryRegisterScope::NewRegister() { | 644 Register TemporaryRegisterScope::NewRegister() { |
| 629 count_++; | 645 count_++; |
| 630 last_register_index_ = builder_->BorrowTemporaryRegister(); | 646 last_register_index_ = builder_->BorrowTemporaryRegister(); |
| 631 return Register(last_register_index_); | 647 return Register(last_register_index_); |
| 632 } | 648 } |
| 633 | 649 |
| 634 } // namespace interpreter | 650 } // namespace interpreter |
| 635 } // namespace internal | 651 } // namespace internal |
| 636 } // namespace v8 | 652 } // namespace v8 |
| OLD | NEW |