mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[vm/bytecode] Collect context levels for compiled code generated from bytecode
Change-Id: Ia2047440e05fce3263f8feb38be4cedd4357ab10 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/112920 Reviewed-by: Régis Crelier <regis@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
parent
5852f5ae92
commit
449446571f
|
@ -993,6 +993,18 @@ Fragment BaseFlowGraphBuilder::StringInterpolate(TokenPosition position) {
|
|||
return Fragment(interpolate);
|
||||
}
|
||||
|
||||
void BaseFlowGraphBuilder::reset_context_depth_for_deopt_id(intptr_t deopt_id) {
|
||||
if (is_recording_context_levels()) {
|
||||
for (intptr_t i = 0, n = context_level_array_->length(); i < n; i += 2) {
|
||||
if (context_level_array_->At(i) == deopt_id) {
|
||||
(*context_level_array_)[i + 1] = context_depth_;
|
||||
return;
|
||||
}
|
||||
ASSERT(context_level_array_->At(i) < deopt_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace dart
|
||||
|
||||
|
|
|
@ -361,6 +361,21 @@ class BaseFlowGraphBuilder {
|
|||
// _StringBase._interpolate call.
|
||||
Fragment StringInterpolate(TokenPosition position);
|
||||
|
||||
// Returns true if we're currently recording deopt_id -> context level
|
||||
// mapping.
|
||||
bool is_recording_context_levels() const {
|
||||
return context_level_array_ != nullptr;
|
||||
}
|
||||
|
||||
// Sets current context level. It will be recorded for all subsequent
|
||||
// deopt ids (until it is adjusted again).
|
||||
void set_context_depth(intptr_t context_level) {
|
||||
context_depth_ = context_level;
|
||||
}
|
||||
|
||||
// Reset context level for the given deopt id (which was allocated earlier).
|
||||
void reset_context_depth_for_deopt_id(intptr_t deopt_id);
|
||||
|
||||
protected:
|
||||
intptr_t AllocateBlockId() { return ++last_used_block_id_; }
|
||||
|
||||
|
|
|
@ -966,6 +966,7 @@ void BytecodeFlowGraphBuilder::BuildDynamicCall() {
|
|||
} else {
|
||||
ASSERT(ic_data_array_->At(deopt_id)->Original() == icdata.raw());
|
||||
}
|
||||
B->reset_context_depth_for_deopt_id(deopt_id);
|
||||
|
||||
const intptr_t argc = DecodeOperandF().value();
|
||||
const ArgumentsDescriptor arg_desc(
|
||||
|
@ -1806,14 +1807,13 @@ static bool IsICDataEntry(const ObjectPool& object_pool, intptr_t index) {
|
|||
// pre-populate ic_data_array_.
|
||||
void BytecodeFlowGraphBuilder::ProcessICDataInObjectPool(
|
||||
const ObjectPool& object_pool) {
|
||||
CompilerState& compiler_state = thread()->compiler_state();
|
||||
ASSERT(compiler_state.deopt_id() == 0);
|
||||
ASSERT(thread()->compiler_state().deopt_id() == 0);
|
||||
|
||||
const intptr_t pool_length = object_pool.Length();
|
||||
for (intptr_t i = 0; i < pool_length; ++i) {
|
||||
if (IsICDataEntry(object_pool, i)) {
|
||||
const ICData& icdata = ICData::CheckedHandle(Z, object_pool.ObjectAt(i));
|
||||
const intptr_t deopt_id = compiler_state.GetNextDeoptId();
|
||||
const intptr_t deopt_id = B->GetNextDeoptId();
|
||||
ASSERT(icdata.deopt_id() == deopt_id);
|
||||
}
|
||||
}
|
||||
|
@ -2017,6 +2017,35 @@ void BytecodeFlowGraphBuilder::CreateParameterVariables() {
|
|||
}
|
||||
}
|
||||
|
||||
#if !defined(PRODUCT)
|
||||
intptr_t BytecodeFlowGraphBuilder::UpdateContextLevel(const Bytecode& bytecode,
|
||||
intptr_t pc) {
|
||||
ASSERT(B->is_recording_context_levels());
|
||||
|
||||
kernel::BytecodeLocalVariablesIterator iter(Z, bytecode);
|
||||
intptr_t context_level = 0;
|
||||
intptr_t next_pc = bytecode_length_;
|
||||
while (iter.MoveNext()) {
|
||||
if (iter.IsScope()) {
|
||||
if (iter.StartPC() <= pc) {
|
||||
if (pc < iter.EndPC()) {
|
||||
// Found enclosing scope. Keep looking as we might find more
|
||||
// scopes (the last one is the most specific).
|
||||
context_level = iter.ContextLevel();
|
||||
next_pc = iter.EndPC();
|
||||
}
|
||||
} else {
|
||||
next_pc = Utils::Minimum(next_pc, iter.StartPC());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
B->set_context_depth(context_level);
|
||||
return next_pc;
|
||||
}
|
||||
#endif // !defined(PRODUCT)
|
||||
|
||||
FlowGraph* BytecodeFlowGraphBuilder::BuildGraph() {
|
||||
const Bytecode& bytecode = Bytecode::Handle(Z, function().bytecode());
|
||||
|
||||
|
@ -2041,6 +2070,11 @@ FlowGraph* BytecodeFlowGraphBuilder::BuildGraph() {
|
|||
kernel::BytecodeSourcePositionsIterator source_pos_iter(Z, bytecode);
|
||||
bool update_position = source_pos_iter.MoveNext();
|
||||
|
||||
#if !defined(PRODUCT)
|
||||
intptr_t next_pc_to_update_context_level =
|
||||
B->is_recording_context_levels() ? 0 : bytecode_length_;
|
||||
#endif
|
||||
|
||||
code_ = Fragment(normal_entry);
|
||||
|
||||
for (pc_ = 0; pc_ < bytecode_length_; pc_ = next_pc_) {
|
||||
|
@ -2073,6 +2107,12 @@ FlowGraph* BytecodeFlowGraphBuilder::BuildGraph() {
|
|||
update_position = source_pos_iter.MoveNext();
|
||||
}
|
||||
|
||||
#if !defined(PRODUCT)
|
||||
if (pc_ >= next_pc_to_update_context_level) {
|
||||
next_pc_to_update_context_level = UpdateContextLevel(bytecode, pc_);
|
||||
}
|
||||
#endif
|
||||
|
||||
BuildInstruction(KernelBytecode::DecodeOpcode(bytecode_instr_));
|
||||
|
||||
if (code_.is_closed()) {
|
||||
|
|
|
@ -167,6 +167,12 @@ class BytecodeFlowGraphBuilder {
|
|||
const ExceptionHandlers& handlers,
|
||||
GraphEntryInstr* graph_entry);
|
||||
|
||||
#if !defined(PRODUCT)
|
||||
// Update context level for the given bytecode PC. returns
|
||||
// next PC where context level might need an update.
|
||||
intptr_t UpdateContextLevel(const Bytecode& bytecode, intptr_t pc);
|
||||
#endif
|
||||
|
||||
// Figure out entry points style.
|
||||
UncheckedEntryPointStyle ChooseEntryPointStyle(
|
||||
const KBCInstr* jump_if_unchecked);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "vm/longjump.h"
|
||||
#include "vm/object_store.h"
|
||||
#include "vm/reusable_handles.h"
|
||||
#include "vm/scopes.h"
|
||||
#include "vm/stack_frame_kbc.h"
|
||||
#include "vm/timeline.h"
|
||||
|
||||
|
@ -3459,11 +3460,7 @@ RawLocalVarDescriptors* BytecodeReader::ComputeLocalVarDescriptors(
|
|||
ASSERT(!bytecode.IsNull());
|
||||
ASSERT(function.bytecode() == bytecode.raw());
|
||||
|
||||
struct VarDesc {
|
||||
const String* name;
|
||||
RawLocalVarDescriptors::VarInfo info;
|
||||
};
|
||||
GrowableArray<VarDesc> vars(8);
|
||||
LocalVarDescriptorsBuilder vars;
|
||||
|
||||
if (function.IsLocalFunction()) {
|
||||
const auto& parent = Function::Handle(zone, function.parent_function());
|
||||
|
@ -3484,8 +3481,8 @@ RawLocalVarDescriptors* BytecodeReader::ComputeLocalVarDescriptors(
|
|||
function.token_pos() <= var_info.end_pos) ||
|
||||
(function.token_pos() <= var_info.begin_pos &&
|
||||
var_info.begin_pos <= function.end_token_pos()))) {
|
||||
vars.Add(
|
||||
VarDesc{&String::Handle(zone, parent_vars.GetName(i)), var_info});
|
||||
vars.Add(LocalVarDescriptorsBuilder::VarDesc{
|
||||
&String::Handle(zone, parent_vars.GetName(i)), var_info});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3501,7 +3498,7 @@ RawLocalVarDescriptors* BytecodeReader::ComputeLocalVarDescriptors(
|
|||
context_level = local_vars.ContextLevel();
|
||||
} break;
|
||||
case BytecodeLocalVariablesIterator::kVariableDeclaration: {
|
||||
VarDesc desc;
|
||||
LocalVarDescriptorsBuilder::VarDesc desc;
|
||||
desc.name = &String::Handle(zone, local_vars.Name());
|
||||
if (local_vars.IsCaptured()) {
|
||||
desc.info.set_kind(RawLocalVarDescriptors::kContextVar);
|
||||
|
@ -3526,7 +3523,7 @@ RawLocalVarDescriptors* BytecodeReader::ComputeLocalVarDescriptors(
|
|||
case BytecodeLocalVariablesIterator::kContextVariable: {
|
||||
ASSERT(local_vars.Index() >= 0);
|
||||
const intptr_t context_variable_index = -local_vars.Index();
|
||||
VarDesc desc;
|
||||
LocalVarDescriptorsBuilder::VarDesc desc;
|
||||
desc.name = &Symbols::CurrentContextVar();
|
||||
desc.info.set_kind(RawLocalVarDescriptors::kSavedCurrentContext);
|
||||
desc.info.scope_id = 0;
|
||||
|
@ -3540,15 +3537,7 @@ RawLocalVarDescriptors* BytecodeReader::ComputeLocalVarDescriptors(
|
|||
}
|
||||
}
|
||||
|
||||
if (vars.is_empty()) {
|
||||
return Object::empty_var_descriptors().raw();
|
||||
}
|
||||
const LocalVarDescriptors& var_desc = LocalVarDescriptors::Handle(
|
||||
zone, LocalVarDescriptors::New(vars.length()));
|
||||
for (intptr_t i = 0; i < vars.length(); i++) {
|
||||
var_desc.SetVar(i, *(vars[i].name), &vars[i].info);
|
||||
}
|
||||
return var_desc.raw();
|
||||
return vars.Done();
|
||||
}
|
||||
#endif // !defined(PRODUCT)
|
||||
|
||||
|
|
|
@ -998,38 +998,43 @@ void Compiler::ComputeLocalVarDescriptors(const Code& code) {
|
|||
ASSERT(code.var_descriptors() == Object::null());
|
||||
// IsIrregexpFunction have eager var descriptors generation.
|
||||
ASSERT(!function.IsIrregexpFunction());
|
||||
if (function.is_declared_in_bytecode()) {
|
||||
auto& var_descs = LocalVarDescriptors::Handle();
|
||||
if (function.HasBytecode()) {
|
||||
const auto& bytecode = Bytecode::Handle(function.bytecode());
|
||||
var_descs = bytecode.GetLocalVarDescriptors();
|
||||
} else {
|
||||
var_descs = Object::empty_var_descriptors().raw();
|
||||
}
|
||||
code.set_var_descriptors(var_descs);
|
||||
return;
|
||||
}
|
||||
// In background compilation, parser can produce 'errors": bailouts
|
||||
// if state changed while compiling in background.
|
||||
CompilerState state(Thread::Current());
|
||||
Thread* thread = Thread::Current();
|
||||
Zone* zone = thread->zone();
|
||||
CompilerState state(thread);
|
||||
LongJumpScope jump;
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
ParsedFunction* parsed_function = new ParsedFunction(
|
||||
Thread::Current(), Function::ZoneHandle(function.raw()));
|
||||
ParsedFunction* parsed_function =
|
||||
new ParsedFunction(thread, Function::ZoneHandle(zone, function.raw()));
|
||||
ZoneGrowableArray<const ICData*>* ic_data_array =
|
||||
new ZoneGrowableArray<const ICData*>();
|
||||
ZoneGrowableArray<intptr_t>* context_level_array =
|
||||
new ZoneGrowableArray<intptr_t>();
|
||||
|
||||
parsed_function->EnsureKernelScopes();
|
||||
kernel::FlowGraphBuilder builder(
|
||||
parsed_function, ic_data_array, context_level_array,
|
||||
/* not inlining */ NULL, false, Compiler::kNoOSRDeoptId);
|
||||
builder.BuildGraph();
|
||||
|
||||
const LocalVarDescriptors& var_descs =
|
||||
LocalVarDescriptors::Handle(parsed_function->scope()->GetVarDescriptors(
|
||||
function, context_level_array));
|
||||
auto& var_descs = LocalVarDescriptors::Handle(zone);
|
||||
|
||||
if (function.is_declared_in_bytecode()) {
|
||||
if (function.HasBytecode()) {
|
||||
const auto& bytecode = Bytecode::Handle(zone, function.bytecode());
|
||||
var_descs = bytecode.GetLocalVarDescriptors();
|
||||
LocalVarDescriptorsBuilder builder;
|
||||
builder.AddDeoptIdToContextLevelMappings(context_level_array);
|
||||
builder.AddAll(zone, var_descs);
|
||||
var_descs = builder.Done();
|
||||
} else {
|
||||
var_descs = Object::empty_var_descriptors().raw();
|
||||
}
|
||||
} else {
|
||||
var_descs = parsed_function->scope()->GetVarDescriptors(
|
||||
function, context_level_array);
|
||||
}
|
||||
|
||||
ASSERT(!var_descs.IsNull());
|
||||
code.set_var_descriptors(var_descs);
|
||||
} else {
|
||||
|
|
|
@ -789,8 +789,10 @@ intptr_t ActivationFrame::ContextLevel() {
|
|||
while (local_vars.MoveNext()) {
|
||||
if (local_vars.Kind() ==
|
||||
kernel::BytecodeLocalVariablesIterator::kScope) {
|
||||
if (local_vars.StartPC() <= pc_offset &&
|
||||
pc_offset <= local_vars.EndPC()) {
|
||||
if (local_vars.StartPC() > pc_offset) {
|
||||
break;
|
||||
}
|
||||
if (pc_offset <= local_vars.EndPC()) {
|
||||
ASSERT(context_level_ <= local_vars.ContextLevel());
|
||||
context_level_ = local_vars.ContextLevel();
|
||||
}
|
||||
|
|
|
@ -296,38 +296,8 @@ static bool IsFilteredIdentifier(const String& str) {
|
|||
RawLocalVarDescriptors* LocalScope::GetVarDescriptors(
|
||||
const Function& func,
|
||||
ZoneGrowableArray<intptr_t>* context_level_array) {
|
||||
GrowableArray<VarDesc> vars(8);
|
||||
|
||||
// Record deopt-id -> context-level mappings, using ranges of deopt-ids with
|
||||
// the same context-level. [context_level_array] contains (deopt_id,
|
||||
// context_level) tuples.
|
||||
for (intptr_t start = 0; start < context_level_array->length();) {
|
||||
intptr_t start_deopt_id = (*context_level_array)[start];
|
||||
intptr_t start_context_level = (*context_level_array)[start + 1];
|
||||
intptr_t end = start;
|
||||
intptr_t end_deopt_id = start_deopt_id;
|
||||
for (intptr_t peek = start + 2; peek < context_level_array->length();
|
||||
peek += 2) {
|
||||
intptr_t peek_deopt_id = (*context_level_array)[peek];
|
||||
intptr_t peek_context_level = (*context_level_array)[peek + 1];
|
||||
// The range encoding assumes the tuples have ascending deopt_ids.
|
||||
ASSERT(peek_deopt_id > end_deopt_id);
|
||||
if (peek_context_level != start_context_level) break;
|
||||
end = peek;
|
||||
end_deopt_id = peek_deopt_id;
|
||||
}
|
||||
|
||||
VarDesc desc;
|
||||
desc.name = &Symbols::Empty(); // No name.
|
||||
desc.info.set_kind(RawLocalVarDescriptors::kContextLevel);
|
||||
desc.info.scope_id = 0;
|
||||
desc.info.begin_pos = TokenPosition(start_deopt_id);
|
||||
desc.info.end_pos = TokenPosition(end_deopt_id);
|
||||
desc.info.set_index(start_context_level);
|
||||
vars.Add(desc);
|
||||
|
||||
start = end + 2;
|
||||
}
|
||||
LocalVarDescriptorsBuilder vars;
|
||||
vars.AddDeoptIdToContextLevelMappings(context_level_array);
|
||||
|
||||
// First enter all variables from scopes of outer functions.
|
||||
const ContextScope& context_scope =
|
||||
|
@ -343,7 +313,7 @@ RawLocalVarDescriptors* LocalScope::GetVarDescriptors(
|
|||
continue;
|
||||
}
|
||||
|
||||
VarDesc desc;
|
||||
LocalVarDescriptorsBuilder::VarDesc desc;
|
||||
desc.name = &name;
|
||||
desc.info.set_kind(kind);
|
||||
desc.info.scope_id = context_scope.ContextLevelAt(i);
|
||||
|
@ -359,20 +329,12 @@ RawLocalVarDescriptors* LocalScope::GetVarDescriptors(
|
|||
int16_t scope_id = 0;
|
||||
CollectLocalVariables(&vars, &scope_id);
|
||||
|
||||
if (vars.length() == 0) {
|
||||
return Object::empty_var_descriptors().raw();
|
||||
}
|
||||
const LocalVarDescriptors& var_desc =
|
||||
LocalVarDescriptors::Handle(LocalVarDescriptors::New(vars.length()));
|
||||
for (int i = 0; i < vars.length(); i++) {
|
||||
var_desc.SetVar(i, *(vars[i].name), &vars[i].info);
|
||||
}
|
||||
return var_desc.raw();
|
||||
return vars.Done();
|
||||
}
|
||||
|
||||
// Add visible variables that are declared in this scope to vars, then
|
||||
// collect visible variables of children, followed by siblings.
|
||||
void LocalScope::CollectLocalVariables(GrowableArray<VarDesc>* vars,
|
||||
void LocalScope::CollectLocalVariables(LocalVarDescriptorsBuilder* vars,
|
||||
int16_t* scope_id) {
|
||||
(*scope_id)++;
|
||||
for (int i = 0; i < this->variables_.length(); i++) {
|
||||
|
@ -381,7 +343,7 @@ void LocalScope::CollectLocalVariables(GrowableArray<VarDesc>* vars,
|
|||
if (var->name().raw() == Symbols::CurrentContextVar().raw()) {
|
||||
// This is the local variable in which the function saves its
|
||||
// own context before calling a closure function.
|
||||
VarDesc desc;
|
||||
LocalVarDescriptorsBuilder::VarDesc desc;
|
||||
desc.name = &var->name();
|
||||
desc.info.set_kind(RawLocalVarDescriptors::kSavedCurrentContext);
|
||||
desc.info.scope_id = 0;
|
||||
|
@ -392,7 +354,7 @@ void LocalScope::CollectLocalVariables(GrowableArray<VarDesc>* vars,
|
|||
vars->Add(desc);
|
||||
} else if (!IsFilteredIdentifier(var->name())) {
|
||||
// This is a regular Dart variable, either stack-based or captured.
|
||||
VarDesc desc;
|
||||
LocalVarDescriptorsBuilder::VarDesc desc;
|
||||
desc.name = &var->name();
|
||||
if (var->is_captured()) {
|
||||
desc.info.set_kind(RawLocalVarDescriptors::kContextVar);
|
||||
|
@ -713,6 +675,62 @@ bool LocalVariable::Equals(const LocalVariable& other) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
void LocalVarDescriptorsBuilder::AddAll(Zone* zone,
|
||||
const LocalVarDescriptors& var_descs) {
|
||||
for (intptr_t i = 0, n = var_descs.Length(); i < n; ++i) {
|
||||
VarDesc desc;
|
||||
desc.name = &String::Handle(zone, var_descs.GetName(i));
|
||||
var_descs.GetInfo(i, &desc.info);
|
||||
Add(desc);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalVarDescriptorsBuilder::AddDeoptIdToContextLevelMappings(
|
||||
ZoneGrowableArray<intptr_t>* context_level_array) {
|
||||
// Record deopt-id -> context-level mappings, using ranges of deopt-ids with
|
||||
// the same context-level. [context_level_array] contains (deopt_id,
|
||||
// context_level) tuples.
|
||||
for (intptr_t start = 0; start < context_level_array->length();) {
|
||||
intptr_t start_deopt_id = (*context_level_array)[start];
|
||||
intptr_t start_context_level = (*context_level_array)[start + 1];
|
||||
intptr_t end = start;
|
||||
intptr_t end_deopt_id = start_deopt_id;
|
||||
for (intptr_t peek = start + 2; peek < context_level_array->length();
|
||||
peek += 2) {
|
||||
intptr_t peek_deopt_id = (*context_level_array)[peek];
|
||||
intptr_t peek_context_level = (*context_level_array)[peek + 1];
|
||||
// The range encoding assumes the tuples have ascending deopt_ids.
|
||||
ASSERT(peek_deopt_id > end_deopt_id);
|
||||
if (peek_context_level != start_context_level) break;
|
||||
end = peek;
|
||||
end_deopt_id = peek_deopt_id;
|
||||
}
|
||||
|
||||
VarDesc desc;
|
||||
desc.name = &Symbols::Empty(); // No name.
|
||||
desc.info.set_kind(RawLocalVarDescriptors::kContextLevel);
|
||||
desc.info.scope_id = 0;
|
||||
desc.info.begin_pos = TokenPosition(start_deopt_id);
|
||||
desc.info.end_pos = TokenPosition(end_deopt_id);
|
||||
desc.info.set_index(start_context_level);
|
||||
Add(desc);
|
||||
|
||||
start = end + 2;
|
||||
}
|
||||
}
|
||||
|
||||
RawLocalVarDescriptors* LocalVarDescriptorsBuilder::Done() {
|
||||
if (vars_.is_empty()) {
|
||||
return Object::empty_var_descriptors().raw();
|
||||
}
|
||||
const LocalVarDescriptors& var_desc =
|
||||
LocalVarDescriptors::Handle(LocalVarDescriptors::New(vars_.length()));
|
||||
for (int i = 0; i < vars_.length(); i++) {
|
||||
var_desc.SetVar(i, *(vars_[i].name), &vars_[i].info);
|
||||
}
|
||||
return var_desc.raw();
|
||||
}
|
||||
|
||||
} // namespace dart
|
||||
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
|
|
@ -215,6 +215,36 @@ class LocalVariable : public ZoneAllocated {
|
|||
DISALLOW_COPY_AND_ASSIGN(LocalVariable);
|
||||
};
|
||||
|
||||
// Accumulates local variable descriptors while building
|
||||
// LocalVarDescriptors object.
|
||||
class LocalVarDescriptorsBuilder : public ValueObject {
|
||||
public:
|
||||
struct VarDesc {
|
||||
const String* name;
|
||||
RawLocalVarDescriptors::VarInfo info;
|
||||
};
|
||||
|
||||
LocalVarDescriptorsBuilder() : vars_(8) {}
|
||||
|
||||
// Add variable descriptor.
|
||||
void Add(const VarDesc& var_desc) { vars_.Add(var_desc); }
|
||||
|
||||
// Add all variable descriptors from given [LocalVarDescriptors] object.
|
||||
void AddAll(Zone* zone, const LocalVarDescriptors& var_descs);
|
||||
|
||||
// Record deopt-id -> context-level mappings, using ranges of deopt-ids with
|
||||
// the same context-level. [context_level_array] contains (deopt_id,
|
||||
// context_level) tuples.
|
||||
void AddDeoptIdToContextLevelMappings(
|
||||
ZoneGrowableArray<intptr_t>* context_level_array);
|
||||
|
||||
// Finish building LocalVarDescriptor object.
|
||||
RawLocalVarDescriptors* Done();
|
||||
|
||||
private:
|
||||
GrowableArray<VarDesc> vars_;
|
||||
};
|
||||
|
||||
class NameReference : public ZoneAllocated {
|
||||
public:
|
||||
NameReference(TokenPosition token_pos, const String& name)
|
||||
|
@ -439,11 +469,6 @@ class LocalScope : public ZoneAllocated {
|
|||
static RawContextScope* CreateImplicitClosureScope(const Function& func);
|
||||
|
||||
private:
|
||||
struct VarDesc {
|
||||
const String* name;
|
||||
RawLocalVarDescriptors::VarInfo info;
|
||||
};
|
||||
|
||||
// Allocate the variable in the current context, possibly updating the current
|
||||
// context owner scope, if the variable is the first one to be allocated at
|
||||
// this loop level.
|
||||
|
@ -452,7 +477,8 @@ class LocalScope : public ZoneAllocated {
|
|||
void AllocateContextVariable(LocalVariable* variable,
|
||||
LocalScope** context_owner);
|
||||
|
||||
void CollectLocalVariables(GrowableArray<VarDesc>* vars, int16_t* scope_id);
|
||||
void CollectLocalVariables(LocalVarDescriptorsBuilder* vars,
|
||||
int16_t* scope_id);
|
||||
|
||||
NameReference* FindReference(const String& name) const;
|
||||
|
||||
|
|
Loading…
Reference in a new issue