| Index: src/interpreter/bytecode-generator.cc
|
| diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc
|
| index 6c51499740581ec24bd49806ee881bdf76d08d6b..3b5b12edfc615a8cd167d8038ef2a64a0a4a2962 100644
|
| --- a/src/interpreter/bytecode-generator.cc
|
| +++ b/src/interpreter/bytecode-generator.cc
|
| @@ -532,6 +532,53 @@ class BytecodeGenerator::RegisterResultScope final
|
| Register result_register_;
|
| };
|
|
|
| +// Used to build a list of global declaration initial value pairs.
|
| +class BytecodeGenerator::GlobalDeclarationsBuilder final : public ZoneObject {
|
| + public:
|
| + GlobalDeclarationsBuilder(Isolate* isolate, Zone* zone)
|
| + : isolate_(isolate),
|
| + declaration_pairs_(0, zone),
|
| + constant_pool_entry_(0),
|
| + has_constant_pool_entry_(false) {}
|
| +
|
| + void AddDeclaration(FeedbackVectorSlot slot, Handle<Object> initial_value) {
|
| + DCHECK(!slot.IsInvalid());
|
| + declaration_pairs_.push_back(handle(Smi::FromInt(slot.ToInt()), isolate_));
|
| + declaration_pairs_.push_back(initial_value);
|
| + }
|
| +
|
| + Handle<FixedArray> AllocateDeclarationPairs() {
|
| + DCHECK(has_constant_pool_entry_);
|
| + int array_index = 0;
|
| + Handle<FixedArray> data = isolate_->factory()->NewFixedArray(
|
| + static_cast<int>(declaration_pairs_.size()), TENURED);
|
| + for (Handle<Object> obj : declaration_pairs_) {
|
| + data->set(array_index++, *obj);
|
| + }
|
| + return data;
|
| + }
|
| +
|
| + size_t constant_pool_entry() {
|
| + DCHECK(has_constant_pool_entry_);
|
| + return constant_pool_entry_;
|
| + }
|
| +
|
| + void set_constant_pool_entry(size_t constant_pool_entry) {
|
| + DCHECK(!empty());
|
| + DCHECK(!has_constant_pool_entry_);
|
| + constant_pool_entry_ = constant_pool_entry;
|
| + has_constant_pool_entry_ = true;
|
| + }
|
| +
|
| + bool empty() { return declaration_pairs_.empty(); }
|
| +
|
| + private:
|
| + Isolate* isolate_;
|
| + ZoneVector<Handle<Object>> declaration_pairs_;
|
| + size_t constant_pool_entry_;
|
| + bool has_constant_pool_entry_;
|
| +};
|
| +
|
| BytecodeGenerator::BytecodeGenerator(CompilationInfo* info)
|
| : isolate_(info->isolate()),
|
| zone_(info->zone()),
|
| @@ -542,7 +589,9 @@ BytecodeGenerator::BytecodeGenerator(CompilationInfo* info)
|
| info->SourcePositionRecordingMode())),
|
| info_(info),
|
| scope_(info->scope()),
|
| - globals_(0, info->zone()),
|
| + globals_builder_(new (zone()) GlobalDeclarationsBuilder(info->isolate(),
|
| + info->zone())),
|
| + global_declarations_(0, info->zone()),
|
| execution_control_(nullptr),
|
| execution_context_(nullptr),
|
| execution_result_(nullptr),
|
| @@ -553,6 +602,20 @@ BytecodeGenerator::BytecodeGenerator(CompilationInfo* info)
|
| }
|
|
|
| Handle<BytecodeArray> BytecodeGenerator::MakeBytecode() {
|
| + GenerateBytecode();
|
| +
|
| + // Build global declaration pair arrays.
|
| + for (GlobalDeclarationsBuilder* globals_builder : global_declarations_) {
|
| + Handle<FixedArray> declarations =
|
| + globals_builder->AllocateDeclarationPairs();
|
| + builder()->InsertConstantPoolEntryAt(globals_builder->constant_pool_entry(),
|
| + declarations);
|
| + }
|
| +
|
| + return builder()->ToBytecodeArray();
|
| +}
|
| +
|
| +void BytecodeGenerator::GenerateBytecode() {
|
| // Initialize the incoming context.
|
| ContextScope incoming_context(this, scope(), false);
|
|
|
| @@ -572,9 +635,9 @@ Handle<BytecodeArray> BytecodeGenerator::MakeBytecode() {
|
| VisitNewLocalFunctionContext();
|
| ContextScope local_function_context(this, scope(), false);
|
| VisitBuildLocalActivationContext();
|
| - MakeBytecodeBody();
|
| + GenerateBytecodeBody();
|
| } else {
|
| - MakeBytecodeBody();
|
| + GenerateBytecodeBody();
|
| }
|
|
|
| // In generator functions, we may not have visited every yield in the AST
|
| @@ -586,10 +649,9 @@ Handle<BytecodeArray> BytecodeGenerator::MakeBytecode() {
|
| }
|
|
|
| builder()->EnsureReturn();
|
| - return builder()->ToBytecodeArray();
|
| }
|
|
|
| -void BytecodeGenerator::MakeBytecodeBody() {
|
| +void BytecodeGenerator::GenerateBytecodeBody() {
|
| // Build the arguments object if it is used.
|
| VisitArgumentsObject(scope()->arguments());
|
|
|
| @@ -723,9 +785,8 @@ void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
|
| case VariableLocation::UNALLOCATED: {
|
| DCHECK(!variable->binding_needs_init());
|
| FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot();
|
| - DCHECK(!slot.IsInvalid());
|
| - globals()->push_back(handle(Smi::FromInt(slot.ToInt()), isolate()));
|
| - globals()->push_back(isolate()->factory()->undefined_value());
|
| + globals_builder()->AddDeclaration(
|
| + slot, isolate()->factory()->undefined_value());
|
| break;
|
| }
|
| case VariableLocation::LOCAL:
|
| @@ -773,9 +834,7 @@ void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
|
| // Check for stack-overflow exception.
|
| if (function.is_null()) return SetStackOverflow();
|
| FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot();
|
| - DCHECK(!slot.IsInvalid());
|
| - globals()->push_back(handle(Smi::FromInt(slot.ToInt()), isolate()));
|
| - globals()->push_back(function);
|
| + globals_builder()->AddDeclaration(slot, function);
|
| break;
|
| }
|
| case VariableLocation::PARAMETER:
|
| @@ -810,34 +869,35 @@ void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
|
| void BytecodeGenerator::VisitDeclarations(
|
| ZoneList<Declaration*>* declarations) {
|
| RegisterAllocationScope register_scope(this);
|
| - DCHECK(globals()->empty());
|
| + DCHECK(globals_builder()->empty());
|
| for (int i = 0; i < declarations->length(); i++) {
|
| RegisterAllocationScope register_scope(this);
|
| Visit(declarations->at(i));
|
| }
|
| - if (globals()->empty()) return;
|
| - int array_index = 0;
|
| - Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
|
| - static_cast<int>(globals()->size()), TENURED);
|
| - for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
|
| + if (globals_builder()->empty()) return;
|
| +
|
| + globals_builder()->set_constant_pool_entry(
|
| + builder()->AllocateConstantPoolEntry());
|
| int encoded_flags = info()->GetDeclareGlobalsFlags();
|
|
|
| register_allocator()->PrepareForConsecutiveAllocations(3);
|
|
|
| Register pairs = register_allocator()->NextConsecutiveRegister();
|
| - builder()->LoadLiteral(data);
|
| - builder()->StoreAccumulatorInRegister(pairs);
|
| -
|
| Register flags = register_allocator()->NextConsecutiveRegister();
|
| - builder()->LoadLiteral(Smi::FromInt(encoded_flags));
|
| - builder()->StoreAccumulatorInRegister(flags);
|
| - DCHECK(flags.index() == pairs.index() + 1);
|
| -
|
| Register function = register_allocator()->NextConsecutiveRegister();
|
| - builder()->MoveRegister(Register::function_closure(), function);
|
|
|
| - builder()->CallRuntime(Runtime::kDeclareGlobalsForInterpreter, pairs, 3);
|
| - globals()->clear();
|
| + // Emit code to declare globals.
|
| + builder()
|
| + ->LoadConstantPoolEntry(globals_builder()->constant_pool_entry())
|
| + .StoreAccumulatorInRegister(pairs)
|
| + .LoadLiteral(Smi::FromInt(encoded_flags))
|
| + .StoreAccumulatorInRegister(flags)
|
| + .MoveRegister(Register::function_closure(), function)
|
| + .CallRuntime(Runtime::kDeclareGlobalsForInterpreter, pairs, 3);
|
| +
|
| + // Push and reset globals builder.
|
| + global_declarations_.push_back(globals_builder());
|
| + globals_builder_ = new (zone()) GlobalDeclarationsBuilder(isolate(), zone());
|
| }
|
|
|
| void BytecodeGenerator::VisitStatements(ZoneList<Statement*>* statements) {
|
|
|