Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/interpreter/bytecode-generator.h" | 5 #include "src/interpreter/bytecode-generator.h" |
| 6 | 6 |
| 7 #include "src/ast/compile-time-value.h" | 7 #include "src/ast/compile-time-value.h" |
| 8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
| 9 #include "src/builtins/builtins-constructor.h" | 9 #include "src/builtins/builtins-constructor.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 491 | 491 |
| 492 // Used to build a list of global declaration initial value pairs. | 492 // Used to build a list of global declaration initial value pairs. |
| 493 class BytecodeGenerator::GlobalDeclarationsBuilder final : public ZoneObject { | 493 class BytecodeGenerator::GlobalDeclarationsBuilder final : public ZoneObject { |
| 494 public: | 494 public: |
| 495 explicit GlobalDeclarationsBuilder(Zone* zone) | 495 explicit GlobalDeclarationsBuilder(Zone* zone) |
| 496 : declarations_(0, zone), | 496 : declarations_(0, zone), |
| 497 constant_pool_entry_(0), | 497 constant_pool_entry_(0), |
| 498 has_constant_pool_entry_(false) {} | 498 has_constant_pool_entry_(false) {} |
| 499 | 499 |
| 500 void AddFunctionDeclaration(Handle<String> name, FeedbackVectorSlot slot, | 500 void AddFunctionDeclaration(Handle<String> name, FeedbackVectorSlot slot, |
| 501 FeedbackVectorSlot literal_slot, | |
| 501 FunctionLiteral* func) { | 502 FunctionLiteral* func) { |
| 502 DCHECK(!slot.IsInvalid()); | 503 DCHECK(!slot.IsInvalid()); |
| 503 declarations_.push_back(Declaration(name, slot, func)); | 504 declarations_.push_back(Declaration(name, slot, literal_slot, func)); |
| 504 } | 505 } |
| 505 | 506 |
| 506 void AddUndefinedDeclaration(Handle<String> name, FeedbackVectorSlot slot) { | 507 void AddUndefinedDeclaration(Handle<String> name, FeedbackVectorSlot slot) { |
| 507 DCHECK(!slot.IsInvalid()); | 508 DCHECK(!slot.IsInvalid()); |
| 508 declarations_.push_back(Declaration(name, slot, nullptr)); | 509 declarations_.push_back(Declaration(name, slot, nullptr)); |
| 509 } | 510 } |
| 510 | 511 |
| 511 Handle<FixedArray> AllocateDeclarations(CompilationInfo* info) { | 512 Handle<FixedArray> AllocateDeclarations(CompilationInfo* info) { |
| 512 DCHECK(has_constant_pool_entry_); | 513 DCHECK(has_constant_pool_entry_); |
| 513 int array_index = 0; | 514 int array_index = 0; |
| 514 Handle<FixedArray> data = info->isolate()->factory()->NewFixedArray( | 515 Handle<FixedArray> data = info->isolate()->factory()->NewFixedArray( |
| 515 static_cast<int>(declarations_.size() * 3), TENURED); | 516 static_cast<int>(declarations_.size() * 4), TENURED); |
| 516 for (const Declaration& declaration : declarations_) { | 517 for (const Declaration& declaration : declarations_) { |
| 517 FunctionLiteral* func = declaration.func; | 518 FunctionLiteral* func = declaration.func; |
| 518 Handle<Object> initial_value; | 519 Handle<Object> initial_value; |
| 519 if (func == nullptr) { | 520 if (func == nullptr) { |
| 520 initial_value = info->isolate()->factory()->undefined_value(); | 521 initial_value = info->isolate()->factory()->undefined_value(); |
| 521 } else { | 522 } else { |
| 522 initial_value = | 523 initial_value = |
| 523 Compiler::GetSharedFunctionInfo(func, info->script(), info); | 524 Compiler::GetSharedFunctionInfo(func, info->script(), info); |
| 524 } | 525 } |
| 525 | 526 |
| 526 // Return a null handle if any initial values can't be created. Caller | 527 // Return a null handle if any initial values can't be created. Caller |
| 527 // will set stack overflow. | 528 // will set stack overflow. |
| 528 if (initial_value.is_null()) return Handle<FixedArray>(); | 529 if (initial_value.is_null()) return Handle<FixedArray>(); |
| 529 | 530 |
| 530 data->set(array_index++, *declaration.name); | 531 data->set(array_index++, *declaration.name); |
| 531 data->set(array_index++, Smi::FromInt(declaration.slot.ToInt())); | 532 data->set(array_index++, Smi::FromInt(declaration.slot.ToInt())); |
| 533 if (declaration.literal_slot.IsInvalid()) { | |
|
Michael Starzinger
2017/01/17 12:48:21
nit: We could pull out the case distinction into a
mvstanton
2017/01/17 13:04:39
Good idea, thanks!
| |
| 534 data->set(array_index++, info->isolate()->heap()->undefined_value()); | |
| 535 } else { | |
| 536 data->set(array_index++, | |
| 537 Smi::FromInt(declaration.literal_slot.ToInt())); | |
| 538 } | |
| 532 data->set(array_index++, *initial_value); | 539 data->set(array_index++, *initial_value); |
| 533 } | 540 } |
| 534 return data; | 541 return data; |
| 535 } | 542 } |
| 536 | 543 |
| 537 size_t constant_pool_entry() { | 544 size_t constant_pool_entry() { |
| 538 DCHECK(has_constant_pool_entry_); | 545 DCHECK(has_constant_pool_entry_); |
| 539 return constant_pool_entry_; | 546 return constant_pool_entry_; |
| 540 } | 547 } |
| 541 | 548 |
| 542 void set_constant_pool_entry(size_t constant_pool_entry) { | 549 void set_constant_pool_entry(size_t constant_pool_entry) { |
| 543 DCHECK(!empty()); | 550 DCHECK(!empty()); |
| 544 DCHECK(!has_constant_pool_entry_); | 551 DCHECK(!has_constant_pool_entry_); |
| 545 constant_pool_entry_ = constant_pool_entry; | 552 constant_pool_entry_ = constant_pool_entry; |
| 546 has_constant_pool_entry_ = true; | 553 has_constant_pool_entry_ = true; |
| 547 } | 554 } |
| 548 | 555 |
| 549 bool empty() { return declarations_.empty(); } | 556 bool empty() { return declarations_.empty(); } |
| 550 | 557 |
| 551 private: | 558 private: |
| 552 struct Declaration { | 559 struct Declaration { |
| 553 Declaration() : slot(FeedbackVectorSlot::Invalid()), func(nullptr) {} | 560 Declaration() : slot(FeedbackVectorSlot::Invalid()), func(nullptr) {} |
| 554 Declaration(Handle<String> name, FeedbackVectorSlot slot, | 561 Declaration(Handle<String> name, FeedbackVectorSlot slot, |
| 562 FeedbackVectorSlot literal_slot, FunctionLiteral* func) | |
| 563 : name(name), slot(slot), literal_slot(literal_slot), func(func) {} | |
| 564 Declaration(Handle<String> name, FeedbackVectorSlot slot, | |
| 555 FunctionLiteral* func) | 565 FunctionLiteral* func) |
| 556 : name(name), slot(slot), func(func) {} | 566 : name(name), slot(slot), func(func) {} |
|
Michael Starzinger
2017/01/17 12:48:21
nit: Let's explicitly initialize the {literal_slot
mvstanton
2017/01/17 13:04:39
Done.
| |
| 557 | 567 |
| 558 Handle<String> name; | 568 Handle<String> name; |
| 559 FeedbackVectorSlot slot; | 569 FeedbackVectorSlot slot; |
| 570 FeedbackVectorSlot literal_slot; | |
| 560 FunctionLiteral* func; | 571 FunctionLiteral* func; |
| 561 }; | 572 }; |
| 562 ZoneVector<Declaration> declarations_; | 573 ZoneVector<Declaration> declarations_; |
| 563 size_t constant_pool_entry_; | 574 size_t constant_pool_entry_; |
| 564 bool has_constant_pool_entry_; | 575 bool has_constant_pool_entry_; |
| 565 }; | 576 }; |
| 566 | 577 |
| 567 BytecodeGenerator::BytecodeGenerator(CompilationInfo* info) | 578 BytecodeGenerator::BytecodeGenerator(CompilationInfo* info) |
| 568 : zone_(info->zone()), | 579 : zone_(info->zone()), |
| 569 builder_(new (zone()) BytecodeArrayBuilder( | 580 builder_(new (zone()) BytecodeArrayBuilder( |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 859 break; | 870 break; |
| 860 } | 871 } |
| 861 } | 872 } |
| 862 | 873 |
| 863 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { | 874 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { |
| 864 Variable* variable = decl->proxy()->var(); | 875 Variable* variable = decl->proxy()->var(); |
| 865 DCHECK(variable->mode() == LET || variable->mode() == VAR); | 876 DCHECK(variable->mode() == LET || variable->mode() == VAR); |
| 866 switch (variable->location()) { | 877 switch (variable->location()) { |
| 867 case VariableLocation::UNALLOCATED: { | 878 case VariableLocation::UNALLOCATED: { |
| 868 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); | 879 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); |
| 869 globals_builder()->AddFunctionDeclaration(variable->name(), slot, | 880 globals_builder()->AddFunctionDeclaration( |
| 870 decl->fun()); | 881 variable->name(), slot, decl->fun()->LiteralFeedbackSlot(), |
| 882 decl->fun()); | |
| 871 break; | 883 break; |
| 872 } | 884 } |
| 873 case VariableLocation::PARAMETER: | 885 case VariableLocation::PARAMETER: |
| 874 case VariableLocation::LOCAL: { | 886 case VariableLocation::LOCAL: { |
| 875 VisitForAccumulatorValue(decl->fun()); | 887 VisitForAccumulatorValue(decl->fun()); |
| 876 BuildVariableAssignment(variable, Token::INIT, | 888 BuildVariableAssignment(variable, Token::INIT, |
| 877 FeedbackVectorSlot::Invalid(), | 889 FeedbackVectorSlot::Invalid(), |
| 878 HoleCheckMode::kElided); | 890 HoleCheckMode::kElided); |
| 879 break; | 891 break; |
| 880 } | 892 } |
| (...skipping 2440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3321 } | 3333 } |
| 3322 | 3334 |
| 3323 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { | 3335 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { |
| 3324 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 3336 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict |
| 3325 : Runtime::kStoreKeyedToSuper_Sloppy; | 3337 : Runtime::kStoreKeyedToSuper_Sloppy; |
| 3326 } | 3338 } |
| 3327 | 3339 |
| 3328 } // namespace interpreter | 3340 } // namespace interpreter |
| 3329 } // namespace internal | 3341 } // namespace internal |
| 3330 } // namespace v8 | 3342 } // namespace v8 |
| OLD | NEW |