diff --git a/runtime/vm/kernel.h b/runtime/vm/kernel.h index 49649aff87e..65a681bf9e5 100644 --- a/runtime/vm/kernel.h +++ b/runtime/vm/kernel.h @@ -434,9 +434,14 @@ class TreeNode : public Node { virtual void AcceptVisitor(Visitor* visitor); virtual void AcceptTreeVisitor(TreeVisitor* visitor) = 0; + intptr_t kernel_offset() { return kernel_offset_; } protected: - TreeNode() {} + TreeNode() : kernel_offset_(-1) {} + + // Offset for this node in the kernel-binary. If this node has a tag the + // offset includes the tag. Can be -1 to indicate "unknown" or invalid offset. + intptr_t kernel_offset_; private: DISALLOW_COPY_AND_ASSIGN(TreeNode); @@ -2450,7 +2455,7 @@ class VariableDeclaration : public Statement { }; static VariableDeclaration* ReadFrom(Reader* reader); - static VariableDeclaration* ReadFromImpl(Reader* reader); + static VariableDeclaration* ReadFromImpl(Reader* reader, bool read_tag); virtual ~VariableDeclaration(); diff --git a/runtime/vm/kernel_binary.cc b/runtime/vm/kernel_binary.cc index f3a41045722..a1cad8377e2 100644 --- a/runtime/vm/kernel_binary.cc +++ b/runtime/vm/kernel_binary.cc @@ -328,7 +328,7 @@ class ReaderHelper { class Reader { public: - Reader(const uint8_t* buffer, int64_t size) + Reader(const uint8_t* buffer, intptr_t size) : buffer_(buffer), size_(size), offset_(0) {} uint32_t ReadUInt32() { @@ -444,13 +444,13 @@ class Reader { if (offset_ != size_) { FATAL2( "Reading Kernel file: Expected to be at EOF " - "(offset: %" Pd64 ", size: %" Pd64 ")", + "(offset: %" Pd ", size: %" Pd ")", offset_, size_); } } void DumpOffset(const char* str) { - OS::PrintErr("@%" Pd64 " %s\n", offset_, str); + OS::PrintErr("@%" Pd " %s\n", offset_, str); } // The largest position read yet (since last reset). @@ -501,10 +501,12 @@ class Reader { return name; } + intptr_t offset() { return offset_; } + private: const uint8_t* buffer_; - int64_t size_; - int64_t offset_; + intptr_t size_; + intptr_t offset_; ReaderHelper builder_; TokenPosition max_position_; TokenPosition min_position_; @@ -636,7 +638,7 @@ class VariableDeclarationImpl { public: static VariableDeclaration* ReadFrom(Reader* reader) { TRACE_READ_OFFSET(); - return VariableDeclaration::ReadFromImpl(reader); + return VariableDeclaration::ReadFromImpl(reader, false); } }; @@ -803,6 +805,7 @@ String* Reference::ReadStringFrom(Reader* reader) { Field* Field::ReadFrom(Reader* reader) { TRACE_READ_OFFSET(); + kernel_offset_ = reader->offset(); // Notice the ReadTag() below. Tag tag = reader->ReadTag(); ASSERT(tag == kField); @@ -919,7 +922,7 @@ RedirectingInitializer* RedirectingInitializer::ReadFromImpl(Reader* reader) { LocalInitializer* LocalInitializer::ReadFromImpl(Reader* reader) { TRACE_READ_OFFSET(); LocalInitializer* init = new LocalInitializer(); - init->variable_ = VariableDeclaration::ReadFromImpl(reader); + init->variable_ = VariableDeclaration::ReadFromImpl(reader, false); return init; } @@ -1387,6 +1390,7 @@ FunctionExpression* FunctionExpression::ReadFrom(Reader* reader) { TRACE_READ_OFFSET(); VariableScope parameters(reader->helper()); FunctionExpression* expr = new FunctionExpression(); + expr->kernel_offset_ = reader->offset() - 1; // -1 to include tag byte. expr->function_ = FunctionNode::ReadFrom(reader); return expr; } @@ -1398,7 +1402,8 @@ Let* Let::ReadFrom(Reader* reader) { PositionScope scope(reader); Let* let = new Let(); - let->variable_ = VariableDeclaration::ReadFromImpl(reader); + let->kernel_offset_ = reader->offset() - 1; // -1 to include tag byte. + let->variable_ = VariableDeclaration::ReadFromImpl(reader, false); let->body_ = Expression::ReadFrom(reader); let->position_ = reader->min_position(); let->end_position_ = reader->max_position(); @@ -1450,7 +1455,7 @@ Statement* Statement::ReadFrom(Reader* reader) { case kYieldStatement: return YieldStatement::ReadFrom(reader); case kVariableDeclaration: - return VariableDeclaration::ReadFromImpl(reader); + return VariableDeclaration::ReadFromImpl(reader, true); case kFunctionDeclaration: return FunctionDeclaration::ReadFrom(reader); default: @@ -1478,6 +1483,7 @@ Block* Block::ReadFromImpl(Reader* reader) { VariableScope vars(reader->helper()); Block* block = new Block(); + block->kernel_offset_ = reader->offset() - 1; // -1 to include tag byte. block->statements().ReadFromStatic(reader); block->position_ = reader->min_position(); block->end_position_ = reader->max_position(); @@ -1544,6 +1550,7 @@ ForStatement* ForStatement::ReadFrom(Reader* reader) { PositionScope scope(reader); ForStatement* forstmt = new ForStatement(); + forstmt->kernel_offset_ = reader->offset() - 1; // -1 to include tag byte. forstmt->variables_.ReadFromStatic(reader); forstmt->condition_ = reader->ReadOptional(); forstmt->updates_.ReadFromStatic(reader); @@ -1561,9 +1568,10 @@ ForInStatement* ForInStatement::ReadFrom(Reader* reader, bool is_async) { PositionScope scope(reader); ForInStatement* forinstmt = new ForInStatement(); + forinstmt->kernel_offset_ = reader->offset() - 1; // -1 to include tag byte. forinstmt->is_async_ = is_async; forinstmt->position_ = reader->ReadPosition(); - forinstmt->variable_ = VariableDeclaration::ReadFromImpl(reader); + forinstmt->variable_ = VariableDeclaration::ReadFromImpl(reader, false); forinstmt->iterable_ = Expression::ReadFrom(reader); forinstmt->body_ = Statement::ReadFrom(reader); forinstmt->end_position_ = reader->max_position(); @@ -1655,6 +1663,7 @@ Catch* Catch::ReadFrom(Reader* reader) { PositionScope scope(reader); Catch* c = new Catch(); + c->kernel_offset_ = reader->offset(); // Catch has no tag. c->guard_ = DartType::ReadFrom(reader); c->exception_ = reader->ReadOptional(); @@ -1692,15 +1701,18 @@ VariableDeclaration* VariableDeclaration::ReadFrom(Reader* reader) { TRACE_READ_OFFSET(); Tag tag = reader->ReadTag(); ASSERT(tag == kVariableDeclaration); - return VariableDeclaration::ReadFromImpl(reader); + return VariableDeclaration::ReadFromImpl(reader, true); } -VariableDeclaration* VariableDeclaration::ReadFromImpl(Reader* reader) { +VariableDeclaration* VariableDeclaration::ReadFromImpl(Reader* reader, + bool read_tag) { TRACE_READ_OFFSET(); PositionScope scope(reader); VariableDeclaration* decl = new VariableDeclaration(); + // -1 or -0 depending on whether there's a tag or not. + decl->kernel_offset_ = reader->offset() - (read_tag ? 1 : 0); decl->position_ = reader->ReadPosition(); decl->equals_position_ = reader->ReadPosition(); decl->flags_ = reader->ReadFlags(); @@ -1722,8 +1734,9 @@ VariableDeclaration* VariableDeclaration::ReadFromImpl(Reader* reader) { FunctionDeclaration* FunctionDeclaration::ReadFrom(Reader* reader) { TRACE_READ_OFFSET(); FunctionDeclaration* decl = new FunctionDeclaration(); + decl->kernel_offset_ = reader->offset() - 1; // -1 to include tag byte. decl->position_ = reader->ReadPosition(); - decl->variable_ = VariableDeclaration::ReadFromImpl(reader); + decl->variable_ = VariableDeclaration::ReadFromImpl(reader, false); VariableScope parameters(reader->helper()); decl->function_ = FunctionNode::ReadFrom(reader); return decl; @@ -1895,6 +1908,7 @@ FunctionNode* FunctionNode::ReadFrom(Reader* reader) { TypeParameterScope scope(reader->helper()); FunctionNode* function = new FunctionNode(); + function->kernel_offset_ = reader->offset(); // FunctionNode has no tag. function->position_ = reader->ReadPosition(); function->end_position_ = reader->ReadPosition(); function->async_marker_ = diff --git a/runtime/vm/kernel_to_il.cc b/runtime/vm/kernel_to_il.cc index 0fc5196ca90..1e0a4064281 100644 --- a/runtime/vm/kernel_to_il.cc +++ b/runtime/vm/kernel_to_il.cc @@ -61,7 +61,8 @@ static void DiscoverEnclosingElements(Zone* zone, void ScopeBuilder::EnterScope(TreeNode* node, TokenPosition start_position) { scope_ = new (Z) LocalScope(scope_, depth_.function_, depth_.loop_); scope_->set_begin_token_pos(start_position); - result_->scopes.Insert(node, scope_); + ASSERT(node->kernel_offset() >= 0); + result_->scopes.Insert(node->kernel_offset(), scope_); } @@ -100,7 +101,7 @@ void ScopeBuilder::AddParameter(VariableDeclaration* declaration, variable->set_is_final(); } scope_->InsertParameterAt(pos, variable); - result_->locals.Insert(declaration, variable); + result_->locals.Insert(declaration->kernel_offset(), variable); // The default value may contain 'let' bindings for which the constant // evaluator needs scope bindings. @@ -185,7 +186,8 @@ void ScopeBuilder::AddIteratorVariable() { void ScopeBuilder::LookupVariable(VariableDeclaration* declaration) { - LocalVariable* variable = result_->locals.Lookup(declaration); + LocalVariable* variable = + result_->locals.Lookup(declaration->kernel_offset()); if (variable == NULL) { // We have not seen a declaration of the variable, so it must be the // case that we are compiling a nested function and the variable is @@ -195,7 +197,7 @@ void ScopeBuilder::LookupVariable(VariableDeclaration* declaration) { const dart::String& name = H.DartSymbol(declaration->name()); variable = current_function_scope_->parent()->LookupVariable(name, true); ASSERT(variable != NULL); - result_->locals.Insert(declaration, variable); + result_->locals.Insert(declaration->kernel_offset(), variable); } if (variable->owner()->function_level() < scope_->function_level()) { // We call `LocalScope->CaptureVariable(variable)` in two scenarios for two @@ -249,7 +251,7 @@ void ScopeBuilder::AddVariable(VariableDeclaration* declaration) { variable->set_is_final(); } scope_->AddVariable(variable); - result_->locals.Insert(declaration, variable); + result_->locals.Insert(declaration->kernel_offset(), variable); } @@ -492,7 +494,7 @@ void ScopeBuilder::HandleLocalFunction(TreeNode* parent, current_function_scope_ = scope_; current_function_node_ = function; if (depth_.function_ == 1) { - FunctionScope function_scope = {function, scope_}; + FunctionScope function_scope = {function->kernel_offset(), scope_}; result_->function_scopes.Add(function_scope); } AddParameters(function); @@ -2014,7 +2016,7 @@ Fragment FlowGraphBuilder::TranslateFinallyFinalizers( Fragment FlowGraphBuilder::EnterScope(TreeNode* node, bool* new_context) { Fragment instructions; const intptr_t context_size = - scopes_->scopes.Lookup(node)->num_context_variables(); + scopes_->scopes.Lookup(node->kernel_offset())->num_context_variables(); if (context_size > 0) { instructions += PushContext(context_size); instructions += Drop(); @@ -2029,7 +2031,7 @@ Fragment FlowGraphBuilder::EnterScope(TreeNode* node, bool* new_context) { Fragment FlowGraphBuilder::ExitScope(TreeNode* node) { Fragment instructions; const intptr_t context_size = - scopes_->scopes.Lookup(node)->num_context_variables(); + scopes_->scopes.Lookup(node->kernel_offset())->num_context_variables(); if (context_size > 0) { instructions += PopContext(); } @@ -2882,7 +2884,7 @@ intptr_t FlowGraphBuilder::CurrentTryIndex() { dart::LocalVariable* FlowGraphBuilder::LookupVariable( VariableDeclaration* var) { - LocalVariable* local = scopes_->locals.Lookup(var); + LocalVariable* local = scopes_->locals.Lookup(var->kernel_offset()); ASSERT(local != NULL); return local; } @@ -6257,7 +6259,9 @@ Fragment FlowGraphBuilder::TranslateFunctionNode(FunctionNode* node, // function and token position. Function& function = Function::ZoneHandle(Z); for (intptr_t i = 0; i < scopes_->function_scopes.length(); ++i) { - if (scopes_->function_scopes[i].function != node) continue; + if (scopes_->function_scopes[i].kernel_offset != node->kernel_offset()) { + continue; + } TokenPosition position = node->position(); if (parent->IsFunctionDeclaration()) { diff --git a/runtime/vm/kernel_to_il.h b/runtime/vm/kernel_to_il.h index e6033eb45cf..1a58d4f8308 100644 --- a/runtime/vm/kernel_to_il.h +++ b/runtime/vm/kernel_to_il.h @@ -81,6 +81,54 @@ class Map : public DirectChainedHashMap > { } }; + +template +class IntKeyRawPointerValueTrait { + public: + typedef intptr_t Key; + typedef V Value; + + struct Pair { + Key key; + Value value; + Pair() : key(NULL), value() {} + Pair(const Key key, const Value& value) : key(key), value(value) {} + Pair(const Pair& other) : key(other.key), value(other.value) {} + }; + + static Key KeyOf(Pair kv) { return kv.key; } + static Value ValueOf(Pair kv) { return kv.value; } + static intptr_t Hashcode(Key key) { return key; } + static bool IsKeyEqual(Pair kv, Key key) { return kv.key == key; } +}; + +template +class IntMap : public DirectChainedHashMap > { + public: + typedef typename IntKeyRawPointerValueTrait::Key Key; + typedef typename IntKeyRawPointerValueTrait::Value Value; + typedef typename IntKeyRawPointerValueTrait::Pair Pair; + + inline void Insert(const Key& key, const Value& value) { + Pair pair(key, value); + DirectChainedHashMap >::Insert(pair); + } + + inline V Lookup(const Key& key) { + Pair* pair = + DirectChainedHashMap >::Lookup(key); + if (pair == NULL) { + return V(); + } else { + return pair->value; + } + } + + inline Pair* LookupPair(const Key& key) { + return DirectChainedHashMap >::Lookup(key); + } +}; + template class MallocMap : public MallocDirectChainedHashMap > { @@ -502,7 +550,7 @@ class ConstantEvaluator : public ExpressionVisitor { struct FunctionScope { - FunctionNode* function; + intptr_t kernel_offset; LocalScope* scope; }; @@ -518,8 +566,8 @@ class ScopeBuildingResult : public ZoneAllocated { yield_jump_variable(NULL), yield_context_variable(NULL) {} - Map locals; - Map scopes; + IntMap locals; + IntMap scopes; GrowableArray function_scopes; // Only non-NULL for instance functions.