From 0a95f8982cfc1d2c29908c18a0c757c838d990c0 Mon Sep 17 00:00:00 2001 From: "svenpanne@chromium.org" Date: Mon, 6 Oct 2014 12:56:11 +0000 Subject: [PATCH] Squeeze the layout of variable proxy nodes. Around 200MB less peak memory usage in the bug mentioned below. BUG=417697 LOG=y R=dcarney@chromium.org Review URL: https://codereview.chromium.org/629983002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24413 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/ast.cc | 23 +++++++++++------------ src/ast.h | 39 +++++++++++++++++++++++++++++---------- src/parser.cc | 2 +- src/rewriter.cc | 5 ++--- src/scopes.cc | 2 +- 5 files changed, 44 insertions(+), 27 deletions(-) diff --git a/src/ast.cc b/src/ast.cc index 2d96f3f..90320f7 100644 --- a/src/ast.cc +++ b/src/ast.cc @@ -62,12 +62,12 @@ bool Expression::IsUndefinedLiteral(Isolate* isolate) const { VariableProxy::VariableProxy(Zone* zone, Variable* var, int position, IdGen* id_gen) : Expression(zone, position, id_gen), - name_(var->raw_name()), - var_(NULL), // Will be set by the call to BindTo. + raw_name_(var->raw_name()), + interface_(var->interface()), + variable_feedback_slot_(kInvalidFeedbackSlot), is_this_(var->is_this()), is_assigned_(false), - interface_(var->interface()), - variable_feedback_slot_(kInvalidFeedbackSlot) { + is_resolved_(false) { BindTo(var); } @@ -75,25 +75,24 @@ VariableProxy::VariableProxy(Zone* zone, Variable* var, int position, VariableProxy::VariableProxy(Zone* zone, const AstRawString* name, bool is_this, Interface* interface, int position, IdGen* id_gen) : Expression(zone, position, id_gen), - name_(name), - var_(NULL), + raw_name_(name), + interface_(interface), + variable_feedback_slot_(kInvalidFeedbackSlot), is_this_(is_this), is_assigned_(false), - interface_(interface), - variable_feedback_slot_(kInvalidFeedbackSlot) {} + is_resolved_(false) {} void VariableProxy::BindTo(Variable* var) { - DCHECK(var_ == NULL); // must be bound only once - DCHECK(var != NULL); // must bind DCHECK(!FLAG_harmony_modules || interface_->IsUnified(var->interface())); - DCHECK((is_this() && var->is_this()) || name_ == var->raw_name()); + DCHECK((is_this() && var->is_this()) || raw_name() == var->raw_name()); // Ideally CONST-ness should match. However, this is very hard to achieve // because we don't know the exact semantics of conflicting (const and // non-const) multiple variable declarations, const vars introduced via // eval() etc. Const-ness and variable declarations are a complete mess // in JS. Sigh... - var_ = var; + set_var(var); + set_is_resolved(); var->set_is_used(); } diff --git a/src/ast.h b/src/ast.h index 5ef4713..11dda68 100644 --- a/src/ast.h +++ b/src/ast.h @@ -1636,20 +1636,36 @@ class VariableProxy FINAL : public Expression { DECLARE_NODE_TYPE(VariableProxy) virtual bool IsValidReferenceExpression() const OVERRIDE { - return var_ == NULL ? true : var_->IsValidReference(); + return !is_resolved() || var()->IsValidReference(); } - bool IsArguments() const { return var_ != NULL && var_->is_arguments(); } + bool IsArguments() const { return is_resolved() && var()->is_arguments(); } + + Handle name() const { return raw_name()->string(); } + const AstRawString* raw_name() const { + return is_resolved() ? var_->raw_name() : raw_name_; + } + + Variable* var() const { + DCHECK(is_resolved()); + return var_; + } + void set_var(Variable* v) { + DCHECK(!is_resolved()); + DCHECK_NOT_NULL(v); + var_ = v; + } - Handle name() const { return name_->string(); } - const AstRawString* raw_name() const { return name_; } - Variable* var() const { return var_; } bool is_this() const { return is_this_; } - Interface* interface() const { return interface_; } bool is_assigned() const { return is_assigned_; } void set_is_assigned() { is_assigned_ = true; } + bool is_resolved() const { return is_resolved_; } + void set_is_resolved() { is_resolved_ = true; } + + Interface* interface() const { return interface_; } + // Bind this proxy to the variable var. Interfaces must match. void BindTo(Variable* var); @@ -1666,12 +1682,15 @@ class VariableProxy FINAL : public Expression { VariableProxy(Zone* zone, const AstRawString* name, bool is_this, Interface* interface, int position, IdGen* id_gen); - const AstRawString* name_; - Variable* var_; // resolved variable, or NULL - bool is_this_; - bool is_assigned_; + union { + const AstRawString* raw_name_; // if !is_resolved_ + Variable* var_; // if is_resolved_ + }; Interface* interface_; int variable_feedback_slot_; + bool is_this_ : 1; + bool is_assigned_ : 1; + bool is_resolved_ : 1; }; diff --git a/src/parser.cc b/src/parser.cc index ec7605b..ef9069c 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -2259,7 +2259,7 @@ Block* Parser::ParseVariableDeclarations( } // Record the end position of the initializer. - if (proxy->var() != NULL) { + if (proxy->is_resolved()) { proxy->var()->set_initializer_position(position()); } diff --git a/src/rewriter.cc b/src/rewriter.cc index 867229a..8616960 100644 --- a/src/rewriter.cc +++ b/src/rewriter.cc @@ -253,9 +253,8 @@ bool Rewriter::Rewrite(CompilationInfo* info) { // the end position of the function generated for executing the eval code // coincides with the end of the with scope which is the position of '1'. int pos = function->end_position(); - VariableProxy* result_proxy = processor.factory()->NewVariableProxy( - result->raw_name(), false, result->interface(), pos); - result_proxy->BindTo(result); + VariableProxy* result_proxy = + processor.factory()->NewVariableProxy(result, pos); Statement* result_statement = processor.factory()->NewReturnStatement(result_proxy, pos); body->Add(result_statement, info->zone()); diff --git a/src/scopes.cc b/src/scopes.cc index 440c7f2..de364a5 100644 --- a/src/scopes.cc +++ b/src/scopes.cc @@ -1031,7 +1031,7 @@ bool Scope::ResolveVariable(CompilationInfo* info, // If the proxy is already resolved there's nothing to do // (functions and consts may be resolved by the parser). - if (proxy->var() != NULL) return true; + if (proxy->is_resolved()) return true; // Otherwise, try to resolve the variable. BindingKind binding_kind; -- 2.7.4