aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/ast
diff options
context:
space:
mode:
authorMyles Borins <mylesborins@google.com>2017-08-01 11:36:44 -0500
committerMyles Borins <mylesborins@google.com>2017-08-01 15:23:15 -0500
commit0a66b223e149a841669bfad5598e4254589730cb (patch)
tree5ec050f7f78aafbf5b1e0e50d639fb843141e162 /deps/v8/src/ast
parent1782b3836ba58ef0da6b687f2bb970c0bd8199ad (diff)
downloadandroid-node-v8-0a66b223e149a841669bfad5598e4254589730cb.tar.gz
android-node-v8-0a66b223e149a841669bfad5598e4254589730cb.tar.bz2
android-node-v8-0a66b223e149a841669bfad5598e4254589730cb.zip
deps: update V8 to 6.0.286.52
PR-URL: https://github.com/nodejs/node/pull/14004 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Diffstat (limited to 'deps/v8/src/ast')
-rw-r--r--deps/v8/src/ast/ast-expression-rewriter.cc2
-rw-r--r--deps/v8/src/ast/ast-numbering.cc3
-rw-r--r--deps/v8/src/ast/ast-types.cc8
-rw-r--r--deps/v8/src/ast/ast-value-factory.cc10
-rw-r--r--deps/v8/src/ast/ast-value-factory.h21
-rw-r--r--deps/v8/src/ast/ast.cc106
-rw-r--r--deps/v8/src/ast/ast.h198
-rw-r--r--deps/v8/src/ast/compile-time-value.cc20
-rw-r--r--deps/v8/src/ast/compile-time-value.h15
-rw-r--r--deps/v8/src/ast/scopes.cc86
-rw-r--r--deps/v8/src/ast/scopes.h20
-rw-r--r--deps/v8/src/ast/variables.cc1
-rw-r--r--deps/v8/src/ast/variables.h51
13 files changed, 311 insertions, 230 deletions
diff --git a/deps/v8/src/ast/ast-expression-rewriter.cc b/deps/v8/src/ast/ast-expression-rewriter.cc
index d23612f2b4..a3ee43204a 100644
--- a/deps/v8/src/ast/ast-expression-rewriter.cc
+++ b/deps/v8/src/ast/ast-expression-rewriter.cc
@@ -31,7 +31,7 @@ void AstExpressionRewriter::VisitDeclarations(Declaration::List* declarations) {
void AstExpressionRewriter::VisitStatements(ZoneList<Statement*>* statements) {
for (int i = 0; i < statements->length(); i++) {
AST_REWRITE_LIST_ELEMENT(Statement, statements, i);
- // Not stopping when a jump statement is found.
+ if (statements->at(i)->IsJump()) break;
}
}
diff --git a/deps/v8/src/ast/ast-numbering.cc b/deps/v8/src/ast/ast-numbering.cc
index 24ccf79244..202b61b17f 100644
--- a/deps/v8/src/ast/ast-numbering.cc
+++ b/deps/v8/src/ast/ast-numbering.cc
@@ -563,6 +563,7 @@ void AstNumberingVisitor::VisitClassLiteral(ClassLiteral* node) {
IncrementNodeCount();
DisableFullCodegenAndCrankshaft(kClassLiteral);
node->set_base_id(ReserveIdRange(ClassLiteral::num_ids()));
+ LanguageModeScope language_mode_scope(this, STRICT);
if (node->extends()) Visit(node->extends());
if (node->constructor()) Visit(node->constructor());
if (node->class_variable_proxy()) {
@@ -715,7 +716,7 @@ bool AstNumberingVisitor::Renumber(FunctionLiteral* node) {
node->set_dont_optimize_reason(dont_optimize_reason());
node->set_suspend_count(suspend_count_);
- if (FLAG_trace_opt) {
+ if (FLAG_trace_opt && !FLAG_turbo) {
if (disable_crankshaft_reason_ != kNoReason) {
// TODO(leszeks): This is a quick'n'dirty fix to allow the debug name of
// the function to be accessed in the below print. This DCHECK will fail
diff --git a/deps/v8/src/ast/ast-types.cc b/deps/v8/src/ast/ast-types.cc
index 9e14730c97..8ff1d88351 100644
--- a/deps/v8/src/ast/ast-types.cc
+++ b/deps/v8/src/ast/ast-types.cc
@@ -302,16 +302,13 @@ AstType::bitset AstBitsetType::Lub(i::Map* map) {
case FILLER_TYPE:
case ACCESS_CHECK_INFO_TYPE:
case INTERCEPTOR_INFO_TYPE:
- case CALL_HANDLER_INFO_TYPE:
case PROMISE_RESOLVE_THENABLE_JOB_INFO_TYPE:
case PROMISE_REACTION_JOB_INFO_TYPE:
case FUNCTION_TEMPLATE_INFO_TYPE:
case OBJECT_TEMPLATE_INFO_TYPE:
case ALLOCATION_MEMENTO_TYPE:
- case TYPE_FEEDBACK_INFO_TYPE:
case ALIASED_ARGUMENTS_ENTRY_TYPE:
case DEBUG_INFO_TYPE:
- case BREAK_POINT_INFO_TYPE:
case STACK_FRAME_INFO_TYPE:
case CELL_TYPE:
case WEAK_CELL_TYPE:
@@ -319,7 +316,10 @@ AstType::bitset AstBitsetType::Lub(i::Map* map) {
case TUPLE2_TYPE:
case TUPLE3_TYPE:
case CONTEXT_EXTENSION_TYPE:
- case CONSTANT_ELEMENTS_PAIR_TYPE:
+ case PADDING_TYPE_1:
+ case PADDING_TYPE_2:
+ case PADDING_TYPE_3:
+ case PADDING_TYPE_4:
UNREACHABLE();
return kNone;
}
diff --git a/deps/v8/src/ast/ast-value-factory.cc b/deps/v8/src/ast/ast-value-factory.cc
index 74613c5eae..a304aa0e00 100644
--- a/deps/v8/src/ast/ast-value-factory.cc
+++ b/deps/v8/src/ast/ast-value-factory.cc
@@ -31,6 +31,7 @@
#include "src/char-predicates-inl.h"
#include "src/objects-inl.h"
#include "src/objects.h"
+#include "src/string-hasher.h"
#include "src/utils.h"
namespace v8 {
@@ -189,10 +190,8 @@ bool AstValue::BooleanValue() const {
case SYMBOL:
UNREACHABLE();
break;
- case NUMBER_WITH_DOT:
case NUMBER:
return DoubleToBoolean(number_);
- case SMI_WITH_DOT:
case SMI:
return smi_ != 0;
case BOOLEAN:
@@ -224,11 +223,9 @@ void AstValue::Internalize(Isolate* isolate) {
break;
}
break;
- case NUMBER_WITH_DOT:
case NUMBER:
set_value(isolate->factory()->NewNumber(number_, TENURED));
break;
- case SMI_WITH_DOT:
case SMI:
set_value(handle(Smi::FromInt(smi_), isolate));
break;
@@ -342,9 +339,8 @@ const AstValue* AstValueFactory::NewSymbol(AstSymbol symbol) {
return AddValue(value);
}
-
-const AstValue* AstValueFactory::NewNumber(double number, bool with_dot) {
- AstValue* value = new (zone_) AstValue(number, with_dot);
+const AstValue* AstValueFactory::NewNumber(double number) {
+ AstValue* value = new (zone_) AstValue(number);
return AddValue(value);
}
diff --git a/deps/v8/src/ast/ast-value-factory.h b/deps/v8/src/ast/ast-value-factory.h
index 19452bc325..34e8b9e1c1 100644
--- a/deps/v8/src/ast/ast-value-factory.h
+++ b/deps/v8/src/ast/ast-value-factory.h
@@ -189,10 +189,6 @@ class AstValue : public ZoneObject {
bool IsNumber() const { return IsSmi() || IsHeapNumber(); }
- bool ContainsDot() const {
- return type_ == NUMBER_WITH_DOT || type_ == SMI_WITH_DOT;
- }
-
const AstRawString* AsString() const {
CHECK_EQ(STRING, type_);
return string_;
@@ -236,10 +232,8 @@ class AstValue : public ZoneObject {
bool BooleanValue() const;
- bool IsSmi() const { return type_ == SMI || type_ == SMI_WITH_DOT; }
- bool IsHeapNumber() const {
- return type_ == NUMBER || type_ == NUMBER_WITH_DOT;
- }
+ bool IsSmi() const { return type_ == SMI; }
+ bool IsHeapNumber() const { return type_ == NUMBER; }
bool IsFalse() const { return type_ == BOOLEAN && !bool_; }
bool IsTrue() const { return type_ == BOOLEAN && bool_; }
bool IsUndefined() const { return type_ == UNDEFINED; }
@@ -267,9 +261,7 @@ class AstValue : public ZoneObject {
STRING,
SYMBOL,
NUMBER,
- NUMBER_WITH_DOT,
SMI,
- SMI_WITH_DOT,
BOOLEAN,
NULL_TYPE,
UNDEFINED,
@@ -284,13 +276,13 @@ class AstValue : public ZoneObject {
symbol_ = symbol;
}
- explicit AstValue(double n, bool with_dot) : next_(nullptr) {
+ explicit AstValue(double n) : next_(nullptr) {
int int_value;
if (DoubleToSmiInteger(n, &int_value)) {
- type_ = with_dot ? SMI_WITH_DOT : SMI;
+ type_ = SMI;
smi_ = int_value;
} else {
- type_ = with_dot ? NUMBER_WITH_DOT : NUMBER;
+ type_ = NUMBER;
number_ = n;
}
}
@@ -481,8 +473,7 @@ class AstValueFactory {
V8_EXPORT_PRIVATE const AstValue* NewString(const AstRawString* string);
// A JavaScript symbol (ECMA-262 edition 6).
const AstValue* NewSymbol(AstSymbol symbol);
- V8_EXPORT_PRIVATE const AstValue* NewNumber(double number,
- bool with_dot = false);
+ V8_EXPORT_PRIVATE const AstValue* NewNumber(double number);
const AstValue* NewSmi(uint32_t number);
const AstValue* NewBoolean(bool b);
const AstValue* NewStringList(ZoneList<const AstRawString*>* strings);
diff --git a/deps/v8/src/ast/ast.cc b/deps/v8/src/ast/ast.cc
index d7d70ae433..b367df7dae 100644
--- a/deps/v8/src/ast/ast.cc
+++ b/deps/v8/src/ast/ast.cc
@@ -19,6 +19,7 @@
#include "src/elements.h"
#include "src/objects-inl.h"
#include "src/objects/literal-objects.h"
+#include "src/objects/map.h"
#include "src/property-details.h"
#include "src/property.h"
#include "src/string-stream.h"
@@ -147,8 +148,8 @@ bool Expression::IsValidReferenceExpressionOrThis() const {
bool Expression::IsAnonymousFunctionDefinition() const {
return (IsFunctionLiteral() &&
AsFunctionLiteral()->IsAnonymousFunctionDefinition()) ||
- (IsDoExpression() &&
- AsDoExpression()->IsAnonymousFunctionDefinition());
+ (IsClassLiteral() &&
+ AsClassLiteral()->IsAnonymousFunctionDefinition());
}
void Expression::MarkTail() {
@@ -161,12 +162,6 @@ void Expression::MarkTail() {
}
}
-bool DoExpression::IsAnonymousFunctionDefinition() const {
- // This is specifically to allow DoExpressions to represent ClassLiterals.
- return represented_function_ != nullptr &&
- represented_function_->raw_name()->IsEmpty();
-}
-
bool Statement::IsJump() const {
switch (node_type()) {
#define JUMP_NODE_LIST(V) \
@@ -350,6 +345,23 @@ bool FunctionLiteral::NeedsHomeObject(Expression* expr) {
return expr->AsFunctionLiteral()->scope()->NeedsHomeObject();
}
+void FunctionLiteral::ReplaceBodyAndScope(FunctionLiteral* other) {
+ DCHECK_NULL(body_);
+ DCHECK_NOT_NULL(scope_);
+ DCHECK_NOT_NULL(other->scope());
+
+ Scope* outer_scope = scope_->outer_scope();
+
+ body_ = other->body();
+ scope_ = other->scope();
+ scope_->ReplaceOuterScope(outer_scope);
+#ifdef DEBUG
+ scope_->set_replaced_from_parse_task(true);
+#endif
+
+ function_length_ = other->function_length_;
+}
+
ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value,
Kind kind, bool is_computed_name)
: LiteralProperty(key, value, is_computed_name),
@@ -490,7 +502,7 @@ void ObjectLiteral::AssignFeedbackSlots(FeedbackVectorSpec* spec,
ObjectLiteral::Property* property = properties()->at(property_index);
Expression* value = property->value();
- if (property->kind() != ObjectLiteral::Property::PROTOTYPE) {
+ if (!property->IsPrototype()) {
if (FunctionLiteral::NeedsHomeObject(value)) {
property->SetSlot(spec->AddStoreICSlot(language_mode));
}
@@ -512,7 +524,7 @@ void ObjectLiteral::CalculateEmitStore(Zone* zone) {
for (int i = properties()->length() - 1; i >= 0; i--) {
ObjectLiteral::Property* property = properties()->at(i);
if (property->is_computed_name()) continue;
- if (property->kind() == ObjectLiteral::Property::PROTOTYPE) continue;
+ if (property->IsPrototype()) continue;
Literal* literal = property->key()->AsLiteral();
DCHECK(!literal->IsNullLiteral());
@@ -532,31 +544,42 @@ void ObjectLiteral::CalculateEmitStore(Zone* zone) {
}
}
-
-bool ObjectLiteral::IsBoilerplateProperty(ObjectLiteral::Property* property) {
- return property != NULL &&
- property->kind() != ObjectLiteral::Property::PROTOTYPE;
+void ObjectLiteral::InitFlagsForPendingNullPrototype(int i) {
+ // We still check for __proto__:null after computed property names.
+ for (; i < properties()->length(); i++) {
+ if (properties()->at(i)->IsNullPrototype()) {
+ set_has_null_protoype(true);
+ break;
+ }
+ }
}
void ObjectLiteral::InitDepthAndFlags() {
- if (depth_ > 0) return;
-
- int position = 0;
- // Accumulate the value in local variables and store it at the end.
+ if (is_initialized()) return;
bool is_simple = true;
+ bool has_seen_prototype = false;
int depth_acc = 1;
- uint32_t max_element_index = 0;
+ uint32_t nof_properties = 0;
uint32_t elements = 0;
+ uint32_t max_element_index = 0;
for (int i = 0; i < properties()->length(); i++) {
ObjectLiteral::Property* property = properties()->at(i);
- if (!IsBoilerplateProperty(property)) {
+ if (property->IsPrototype()) {
+ has_seen_prototype = true;
+ // __proto__:null has no side-effects and is set directly on the
+ // boilerplate.
+ if (property->IsNullPrototype()) {
+ set_has_null_protoype(true);
+ continue;
+ }
+ DCHECK(!has_null_prototype());
is_simple = false;
continue;
}
-
- if (static_cast<uint32_t>(position) == boilerplate_properties_ * 2) {
+ if (nof_properties == boilerplate_properties_) {
DCHECK(property->is_computed_name());
is_simple = false;
+ if (!has_seen_prototype) InitFlagsForPendingNullPrototype(i);
break;
}
DCHECK(!property->is_computed_name());
@@ -578,7 +601,7 @@ void ObjectLiteral::InitDepthAndFlags() {
// TODO(verwaest): Remove once we can store them inline.
if (FLAG_track_double_fields &&
(value->IsNumberLiteral() || !is_compile_time_value)) {
- bit_field_ = MayStoreDoublesField::update(bit_field_, true);
+ set_may_store_doubles(true);
}
is_simple = is_simple && is_compile_time_value;
@@ -596,15 +619,12 @@ void ObjectLiteral::InitDepthAndFlags() {
elements++;
}
- // Increment the position for the key and the value.
- position += 2;
+ nof_properties++;
}
- bit_field_ = FastElementsField::update(
- bit_field_,
- (max_element_index <= 32) || ((2 * elements) >= max_element_index));
- bit_field_ = HasElementsField::update(bit_field_, elements > 0);
-
+ set_fast_elements((max_element_index <= 32) ||
+ ((2 * elements) >= max_element_index));
+ set_has_elements(elements > 0);
set_is_simple(is_simple);
set_depth(depth_acc);
}
@@ -616,7 +636,7 @@ void ObjectLiteral::BuildConstantProperties(Isolate* isolate) {
bool has_seen_proto = false;
for (int i = 0; i < properties()->length(); i++) {
ObjectLiteral::Property* property = properties()->at(i);
- if (!IsBoilerplateProperty(property)) {
+ if (property->IsPrototype()) {
has_seen_proto = true;
continue;
}
@@ -641,9 +661,7 @@ void ObjectLiteral::BuildConstantProperties(Isolate* isolate) {
int position = 0;
for (int i = 0; i < properties()->length(); i++) {
ObjectLiteral::Property* property = properties()->at(i);
- if (!IsBoilerplateProperty(property)) {
- continue;
- }
+ if (property->IsPrototype()) continue;
if (static_cast<uint32_t>(position) == boilerplate_properties_ * 2) {
DCHECK(property->is_computed_name());
@@ -693,7 +711,7 @@ ElementsKind ArrayLiteral::constant_elements_kind() const {
void ArrayLiteral::InitDepthAndFlags() {
DCHECK_LT(first_spread_index_, 0);
- if (depth_ > 0) return;
+ if (is_initialized()) return;
int constants_length = values()->length();
@@ -1013,6 +1031,24 @@ void Expression::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
}
}
+void SmallMapList::AddMapIfMissing(Handle<Map> map, Zone* zone) {
+ if (!Map::TryUpdate(map).ToHandle(&map)) return;
+ for (int i = 0; i < length(); ++i) {
+ if (at(i).is_identical_to(map)) return;
+ }
+ Add(map, zone);
+}
+
+void SmallMapList::FilterForPossibleTransitions(Map* root_map) {
+ for (int i = list_.length() - 1; i >= 0; i--) {
+ if (at(i)->FindRootMap() != root_map) {
+ list_.RemoveElement(list_.at(i));
+ }
+ }
+}
+
+Handle<Map> SmallMapList::at(int i) const { return Handle<Map>(list_.at(i)); }
+
SmallMapList* Expression::GetReceiverTypes() {
switch (node_type()) {
#define NODE_LIST(V) \
diff --git a/deps/v8/src/ast/ast.h b/deps/v8/src/ast/ast.h
index 9d7b4de82c..0fc9af621c 100644
--- a/deps/v8/src/ast/ast.h
+++ b/deps/v8/src/ast/ast.h
@@ -252,29 +252,15 @@ class SmallMapList final {
bool is_empty() const { return list_.is_empty(); }
int length() const { return list_.length(); }
- void AddMapIfMissing(Handle<Map> map, Zone* zone) {
- if (!Map::TryUpdate(map).ToHandle(&map)) return;
- for (int i = 0; i < length(); ++i) {
- if (at(i).is_identical_to(map)) return;
- }
- Add(map, zone);
- }
+ void AddMapIfMissing(Handle<Map> map, Zone* zone);
- void FilterForPossibleTransitions(Map* root_map) {
- for (int i = list_.length() - 1; i >= 0; i--) {
- if (at(i)->FindRootMap() != root_map) {
- list_.RemoveElement(list_.at(i));
- }
- }
- }
+ void FilterForPossibleTransitions(Map* root_map);
void Add(Handle<Map> handle, Zone* zone) {
list_.Add(handle.location(), zone);
}
- Handle<Map> at(int i) const {
- return Handle<Map>(list_.at(i));
- }
+ Handle<Map> at(int i) const;
Handle<Map> first() const { return at(0); }
Handle<Map> last() const { return at(length() - 1); }
@@ -484,20 +470,12 @@ class DoExpression final : public Expression {
void set_block(Block* b) { block_ = b; }
VariableProxy* result() { return result_; }
void set_result(VariableProxy* v) { result_ = v; }
- FunctionLiteral* represented_function() { return represented_function_; }
- void set_represented_function(FunctionLiteral* f) {
- represented_function_ = f;
- }
- bool IsAnonymousFunctionDefinition() const;
private:
friend class AstNodeFactory;
DoExpression(Block* block, VariableProxy* result, int pos)
- : Expression(pos, kDoExpression),
- block_(block),
- result_(result),
- represented_function_(nullptr) {
+ : Expression(pos, kDoExpression), block_(block), result_(result) {
DCHECK_NOT_NULL(block_);
DCHECK_NOT_NULL(result_);
}
@@ -506,7 +484,6 @@ class DoExpression final : public Expression {
Block* block_;
VariableProxy* result_;
- FunctionLiteral* represented_function_;
};
@@ -977,11 +954,11 @@ class CaseClause final : public Expression {
CaseClause(Expression* label, ZoneList<Statement*>* statements, int pos);
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+ FeedbackSlot feedback_slot_;
Expression* label_;
Label body_target_;
ZoneList<Statement*>* statements_;
AstType* compare_type_;
- FeedbackSlot feedback_slot_;
};
@@ -1238,9 +1215,9 @@ class Literal final : public Expression {
// Base class for literals that need space in the type feedback vector.
class MaterializedLiteral : public Expression {
public:
+ bool is_initialized() const { return 0 < depth_; }
int depth() const {
- // only callable after initialization.
- DCHECK(depth_ >= 1);
+ DCHECK(is_initialized());
return depth_;
}
@@ -1270,10 +1247,11 @@ class MaterializedLiteral : public Expression {
void set_is_simple(bool is_simple) {
bit_field_ = IsSimpleField::update(bit_field_, is_simple);
}
+
friend class CompileTimeValue;
void set_depth(int depth) {
- DCHECK_LE(1, depth);
+ DCHECK(!is_initialized());
depth_ = depth;
}
@@ -1359,6 +1337,11 @@ class ObjectLiteralProperty final : public LiteralProperty {
void set_receiver_type(Handle<Map> map) { receiver_type_ = map; }
+ bool IsNullPrototype() const {
+ return IsPrototype() && value()->IsNullLiteral();
+ }
+ bool IsPrototype() const { return kind() == PROTOTYPE; }
+
private:
friend class AstNodeFactory;
@@ -1396,9 +1379,9 @@ class ObjectLiteral final : public MaterializedLiteral {
bool has_rest_property() const {
return HasRestPropertyField::decode(bit_field_);
}
-
- // Decide if a property should be in the object boilerplate.
- static bool IsBoilerplateProperty(Property* property);
+ bool has_null_prototype() const {
+ return HasNullPrototypeField::decode(bit_field_);
+ }
// Populate the depth field and flags.
void InitDepthAndFlags();
@@ -1426,12 +1409,16 @@ class ObjectLiteral final : public MaterializedLiteral {
// Assemble bitfield of flags for the CreateObjectLiteral helper.
int ComputeFlags(bool disable_mementos = false) const {
int flags = fast_elements() ? kFastElements : kNoFlags;
- if (has_shallow_properties()) {
- flags |= kShallowProperties;
- }
- if (disable_mementos) {
- flags |= kDisableMementos;
- }
+ if (has_shallow_properties()) flags |= kShallowProperties;
+ if (disable_mementos) flags |= kDisableMementos;
+ if (has_null_prototype()) flags |= kHasNullPrototype;
+ return flags;
+ }
+
+ int EncodeLiteralType() {
+ int flags = fast_elements() ? kFastElements : kNoFlags;
+ if (has_shallow_properties()) flags |= kShallowProperties;
+ if (has_null_prototype()) flags |= kHasNullPrototype;
return flags;
}
@@ -1440,7 +1427,7 @@ class ObjectLiteral final : public MaterializedLiteral {
kFastElements = 1,
kShallowProperties = 1 << 1,
kDisableMementos = 1 << 2,
- kHasRestProperty = 1 << 3,
+ kHasNullPrototype = 1 << 3,
};
struct Accessors: public ZoneObject {
@@ -1476,12 +1463,28 @@ class ObjectLiteral final : public MaterializedLiteral {
bit_field_ |= FastElementsField::encode(false) |
HasElementsField::encode(false) |
MayStoreDoublesField::encode(false) |
- HasRestPropertyField::encode(has_rest_property);
+ HasRestPropertyField::encode(has_rest_property) |
+ HasNullPrototypeField::encode(false);
}
static int parent_num_ids() { return MaterializedLiteral::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+ void InitFlagsForPendingNullPrototype(int i);
+
+ void set_may_store_doubles(bool may_store_doubles) {
+ bit_field_ = MayStoreDoublesField::update(bit_field_, may_store_doubles);
+ }
+ void set_fast_elements(bool fast_elements) {
+ bit_field_ = FastElementsField::update(bit_field_, fast_elements);
+ }
+ void set_has_elements(bool has_elements) {
+ bit_field_ = HasElementsField::update(bit_field_, has_elements);
+ }
+ void set_has_null_protoype(bool has_null_prototype) {
+ bit_field_ = HasNullPrototypeField::update(bit_field_, has_null_prototype);
+ }
+
uint32_t boilerplate_properties_;
Handle<BoilerplateDescription> constant_properties_;
ZoneList<Property*>* properties_;
@@ -1494,6 +1497,8 @@ class ObjectLiteral final : public MaterializedLiteral {
: public BitField<bool, HasElementsField::kNext, 1> {};
class HasRestPropertyField
: public BitField<bool, MayStoreDoublesField::kNext, 1> {};
+ class HasNullPrototypeField
+ : public BitField<bool, HasRestPropertyField::kNext, 1> {};
};
@@ -1582,9 +1587,7 @@ class ArrayLiteral final : public MaterializedLiteral {
// Assemble bitfield of flags for the CreateArrayLiteral helper.
int ComputeFlags(bool disable_mementos = false) const {
int flags = depth() == 1 ? kShallowElements : kNoFlags;
- if (disable_mementos) {
- flags |= kDisableMementos;
- }
+ if (disable_mementos) flags |= kDisableMementos;
return flags;
}
@@ -1668,7 +1671,11 @@ class VariableProxy final : public Expression {
}
HoleCheckMode hole_check_mode() const {
- return HoleCheckModeField::decode(bit_field_);
+ HoleCheckMode mode = HoleCheckModeField::decode(bit_field_);
+ DCHECK_IMPLIES(mode == HoleCheckMode::kRequired,
+ var()->binding_needs_init() ||
+ var()->local_if_not_shadowed()->binding_needs_init());
+ return mode;
}
void set_needs_hole_check() {
bit_field_ =
@@ -2160,10 +2167,10 @@ class BinaryOperation final : public Expression {
BinaryOperation(Token::Value op, Expression* left, Expression* right, int pos)
: Expression(pos, kBinaryOperation),
- has_fixed_right_arg_(false),
- fixed_right_arg_value_(0),
left_(left),
- right_(right) {
+ right_(right),
+ has_fixed_right_arg_(false),
+ fixed_right_arg_value_(0) {
bit_field_ |= OperatorField::encode(op);
DCHECK(Token::IsBinaryOp(op));
}
@@ -2171,14 +2178,14 @@ class BinaryOperation final : public Expression {
static int parent_num_ids() { return Expression::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+ FeedbackSlot feedback_slot_;
+ Expression* left_;
+ Expression* right_;
+ Handle<AllocationSite> allocation_site_;
// TODO(rossberg): the fixed arg should probably be represented as a Constant
// type for the RHS. Currenty it's actually a Maybe<int>
bool has_fixed_right_arg_;
int fixed_right_arg_value_;
- Expression* left_;
- Expression* right_;
- Handle<AllocationSite> allocation_site_;
- FeedbackSlot feedback_slot_;
class OperatorField
: public BitField<Token::Value, Expression::kNextBitFieldIndex, 7> {};
@@ -2306,11 +2313,11 @@ class CompareOperation final : public Expression {
static int parent_num_ids() { return Expression::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
+ FeedbackSlot feedback_slot_;
Expression* left_;
Expression* right_;
-
AstType* combined_type_;
- FeedbackSlot feedback_slot_;
+
class OperatorField
: public BitField<Token::Value, Expression::kNextBitFieldIndex, 7> {};
};
@@ -2645,6 +2652,14 @@ class FunctionLiteral final : public Expression {
bool AllowsLazyCompilation();
+ bool CanSuspend() {
+ if (suspend_count() > 0) {
+ DCHECK(IsResumableFunction(kind()));
+ return true;
+ }
+ return false;
+ }
+
Handle<String> debug_name() const {
if (raw_name_ != NULL && !raw_name_->IsEmpty()) {
return raw_name_->string();
@@ -2742,6 +2757,8 @@ class FunctionLiteral final : public Expression {
function_literal_id_ = function_literal_id;
}
+ void ReplaceBodyAndScope(FunctionLiteral* other);
+
private:
friend class AstNodeFactory;
@@ -2827,6 +2844,7 @@ class ClassLiteral final : public Expression {
public:
typedef ClassLiteralProperty Property;
+ Scope* scope() const { return scope_; }
VariableProxy* class_variable_proxy() const { return class_variable_proxy_; }
Expression* extends() const { return extends_; }
void set_extends(Expression* e) { extends_ = e; }
@@ -2842,6 +2860,13 @@ class ClassLiteral final : public Expression {
return HasStaticComputedNames::decode(bit_field_);
}
+ bool is_anonymous_expression() const {
+ return IsAnonymousExpression::decode(bit_field_);
+ }
+ bool IsAnonymousFunctionDefinition() const {
+ return is_anonymous_expression();
+ }
+
// Object literals need one feedback slot for each non-trivial value, as well
// as some slots for home objects.
void AssignFeedbackSlots(FeedbackVectorSpec* spec, LanguageMode language_mode,
@@ -2858,23 +2883,27 @@ class ClassLiteral final : public Expression {
private:
friend class AstNodeFactory;
- ClassLiteral(VariableProxy* class_variable_proxy, Expression* extends,
- FunctionLiteral* constructor, ZoneList<Property*>* properties,
- int start_position, int end_position,
- bool has_name_static_property, bool has_static_computed_names)
+ ClassLiteral(Scope* scope, VariableProxy* class_variable_proxy,
+ Expression* extends, FunctionLiteral* constructor,
+ ZoneList<Property*>* properties, int start_position,
+ int end_position, bool has_name_static_property,
+ bool has_static_computed_names, bool is_anonymous)
: Expression(start_position, kClassLiteral),
end_position_(end_position),
+ scope_(scope),
class_variable_proxy_(class_variable_proxy),
extends_(extends),
constructor_(constructor),
properties_(properties) {
bit_field_ |= HasNameStaticProperty::encode(has_name_static_property) |
- HasStaticComputedNames::encode(has_static_computed_names);
+ HasStaticComputedNames::encode(has_static_computed_names) |
+ IsAnonymousExpression::encode(is_anonymous);
}
int end_position_;
FeedbackSlot home_object_slot_;
FeedbackSlot proxy_slot_;
+ Scope* scope_;
VariableProxy* class_variable_proxy_;
Expression* extends_;
FunctionLiteral* constructor_;
@@ -2884,6 +2913,8 @@ class ClassLiteral final : public Expression {
: public BitField<bool, Expression::kNextBitFieldIndex, 1> {};
class HasStaticComputedNames
: public BitField<bool, HasNameStaticProperty::kNext, 1> {};
+ class IsAnonymousExpression
+ : public BitField<bool, HasStaticComputedNames::kNext, 1> {};
};
@@ -2909,9 +2940,9 @@ class NativeFunctionLiteral final : public Expression {
name_(name),
extension_(extension) {}
+ FeedbackSlot literal_feedback_slot_;
const AstRawString* name_;
v8::Extension* extension_;
- FeedbackSlot literal_feedback_slot_;
};
@@ -3211,17 +3242,12 @@ class AstVisitor BASE_EMBEDDED {
class AstNodeFactory final BASE_EMBEDDED {
public:
- explicit AstNodeFactory(AstValueFactory* ast_value_factory)
- : zone_(nullptr), ast_value_factory_(ast_value_factory) {
- if (ast_value_factory != nullptr) {
- zone_ = ast_value_factory->zone();
- }
- }
+ AstNodeFactory(AstValueFactory* ast_value_factory, Zone* zone)
+ : zone_(zone), ast_value_factory_(ast_value_factory) {}
AstValueFactory* ast_value_factory() const { return ast_value_factory_; }
void set_ast_value_factory(AstValueFactory* ast_value_factory) {
ast_value_factory_ = ast_value_factory;
- zone_ = ast_value_factory->zone();
}
VariableDeclaration* NewVariableDeclaration(VariableProxy* proxy,
@@ -3370,9 +3396,8 @@ class AstNodeFactory final BASE_EMBEDDED {
return new (zone_) Literal(ast_value_factory_->NewSymbol(symbol), pos);
}
- Literal* NewNumberLiteral(double number, int pos, bool with_dot = false) {
- return new (zone_)
- Literal(ast_value_factory_->NewNumber(number, with_dot), pos);
+ Literal* NewNumberLiteral(double number, int pos) {
+ return new (zone_) Literal(ast_value_factory_->NewNumber(number), pos);
}
Literal* NewSmiLiteral(uint32_t number, int pos) {
@@ -3590,15 +3615,18 @@ class AstNodeFactory final BASE_EMBEDDED {
ClassLiteral::Property(key, value, kind, is_static, is_computed_name);
}
- ClassLiteral* NewClassLiteral(VariableProxy* proxy, Expression* extends,
+ ClassLiteral* NewClassLiteral(Scope* scope, VariableProxy* proxy,
+ Expression* extends,
FunctionLiteral* constructor,
ZoneList<ClassLiteral::Property*>* properties,
int start_position, int end_position,
bool has_name_static_property,
- bool has_static_computed_names) {
- return new (zone_) ClassLiteral(
- proxy, extends, constructor, properties, start_position, end_position,
- has_name_static_property, has_static_computed_names);
+ bool has_static_computed_names,
+ bool is_anonymous) {
+ return new (zone_)
+ ClassLiteral(scope, proxy, extends, constructor, properties,
+ start_position, end_position, has_name_static_property,
+ has_static_computed_names, is_anonymous);
}
NativeFunctionLiteral* NewNativeFunctionLiteral(const AstRawString* name,
@@ -3646,24 +3674,6 @@ class AstNodeFactory final BASE_EMBEDDED {
Zone* zone() const { return zone_; }
void set_zone(Zone* zone) { zone_ = zone; }
- // Handles use of temporary zones when parsing inner function bodies.
- class BodyScope {
- public:
- BodyScope(AstNodeFactory* factory, Zone* temp_zone, bool use_temp_zone)
- : factory_(factory), prev_zone_(factory->zone_) {
- if (use_temp_zone) {
- factory->zone_ = temp_zone;
- }
- }
-
- void Reset() { factory_->zone_ = prev_zone_; }
- ~BodyScope() { Reset(); }
-
- private:
- AstNodeFactory* factory_;
- Zone* prev_zone_;
- };
-
private:
// This zone may be deallocated upon returning from parsing a function body
// which we can guarantee is not going to be compiled or have its AST
diff --git a/deps/v8/src/ast/compile-time-value.cc b/deps/v8/src/ast/compile-time-value.cc
index 27dd29fee0..b86343d059 100644
--- a/deps/v8/src/ast/compile-time-value.cc
+++ b/deps/v8/src/ast/compile-time-value.cc
@@ -24,28 +24,24 @@ Handle<FixedArray> CompileTimeValue::GetValue(Isolate* isolate,
Factory* factory = isolate->factory();
DCHECK(IsCompileTimeValue(expression));
Handle<FixedArray> result = factory->NewFixedArray(2, TENURED);
- ObjectLiteral* object_literal = expression->AsObjectLiteral();
- if (object_literal != NULL) {
+ if (expression->IsObjectLiteral()) {
+ ObjectLiteral* object_literal = expression->AsObjectLiteral();
DCHECK(object_literal->is_simple());
- if (object_literal->fast_elements()) {
- result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
- } else {
- result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
- }
+ int literalTypeFlag = object_literal->EncodeLiteralType();
+ DCHECK_NE(kArrayLiteralFlag, literalTypeFlag);
+ result->set(kLiteralTypeSlot, Smi::FromInt(literalTypeFlag));
result->set(kElementsSlot, *object_literal->constant_properties());
} else {
ArrayLiteral* array_literal = expression->AsArrayLiteral();
DCHECK(array_literal != NULL && array_literal->is_simple());
- result->set(kLiteralTypeSlot, Smi::FromInt(ARRAY_LITERAL));
+ result->set(kLiteralTypeSlot, Smi::FromInt(kArrayLiteralFlag));
result->set(kElementsSlot, *array_literal->constant_elements());
}
return result;
}
-CompileTimeValue::LiteralType CompileTimeValue::GetLiteralType(
- Handle<FixedArray> value) {
- Smi* literal_type = Smi::cast(value->get(kLiteralTypeSlot));
- return static_cast<LiteralType>(literal_type->value());
+int CompileTimeValue::GetLiteralTypeFlags(Handle<FixedArray> value) {
+ return Smi::cast(value->get(kLiteralTypeSlot))->value();
}
Handle<HeapObject> CompileTimeValue::GetElements(Handle<FixedArray> value) {
diff --git a/deps/v8/src/ast/compile-time-value.h b/deps/v8/src/ast/compile-time-value.h
index d61443e583..e8ded43122 100644
--- a/deps/v8/src/ast/compile-time-value.h
+++ b/deps/v8/src/ast/compile-time-value.h
@@ -17,19 +17,20 @@ class Expression;
// can be fully handled at compile time.
class CompileTimeValue : public AllStatic {
public:
- enum LiteralType {
- OBJECT_LITERAL_FAST_ELEMENTS,
- OBJECT_LITERAL_SLOW_ELEMENTS,
- ARRAY_LITERAL
- };
+ // This is a special marker used to encode array literals. The value has to be
+ // different from any value possibly returned by
+ // ObjectLiteral::EncodeLiteralType.
+ static const int kArrayLiteralFlag = -1;
static bool IsCompileTimeValue(Expression* expression);
// Get the value as a compile time value.
static Handle<FixedArray> GetValue(Isolate* isolate, Expression* expression);
- // Get the type of a compile time value returned by GetValue().
- static LiteralType GetLiteralType(Handle<FixedArray> value);
+ // Get the encoded literal type. This can either be kArrayLiteralFlag or
+ // encoded properties of an ObjectLiteral returned by
+ // ObjectLiteral::EncodeLiteralType.
+ static int GetLiteralTypeFlags(Handle<FixedArray> value);
// Get the elements of a compile time value returned by GetValue().
static Handle<HeapObject> GetElements(Handle<FixedArray> value);
diff --git a/deps/v8/src/ast/scopes.cc b/deps/v8/src/ast/scopes.cc
index 99be5cd343..f4c21d7513 100644
--- a/deps/v8/src/ast/scopes.cc
+++ b/deps/v8/src/ast/scopes.cc
@@ -612,7 +612,7 @@ void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) {
Variable* var = DeclareVariableName(name, VAR);
if (var != kDummyPreParserVariable &&
var != kDummyPreParserLexicalVariable) {
- DCHECK(FLAG_preparser_scope_analysis);
+ DCHECK(FLAG_experimental_preparser_scope_analysis);
var->set_maybe_assigned();
}
}
@@ -644,7 +644,7 @@ void DeclarationScope::Analyze(ParseInfo* info, Isolate* isolate,
}
if (scope->is_eval_scope() && is_sloppy(scope->language_mode())) {
- AstNodeFactory factory(info->ast_value_factory());
+ AstNodeFactory factory(info->ast_value_factory(), info->zone());
scope->HoistSloppyBlockFunctions(&factory);
}
@@ -662,7 +662,7 @@ void DeclarationScope::Analyze(ParseInfo* info, Isolate* isolate,
scope->set_should_eager_compile();
if (scope->must_use_preparsed_scope_data_) {
- DCHECK(FLAG_preparser_scope_analysis);
+ DCHECK(FLAG_experimental_preparser_scope_analysis);
DCHECK_NOT_NULL(info->preparsed_scope_data());
DCHECK_EQ(scope->scope_type_, ScopeType::FUNCTION_SCOPE);
info->preparsed_scope_data()->RestoreData(scope);
@@ -1044,7 +1044,7 @@ Variable* DeclarationScope::DeclareParameterName(
if (name == ast_value_factory->arguments_string()) {
has_arguments_parameter_ = true;
}
- if (FLAG_preparser_scope_analysis) {
+ if (FLAG_experimental_preparser_scope_analysis) {
Variable* var = Declare(zone(), name, VAR);
params_.Add(var, zone());
return var;
@@ -1205,7 +1205,7 @@ Variable* Scope::DeclareVariableName(const AstRawString* name,
DCHECK(scope_info_.is_null());
// Declare the variable in the declaration scope.
- if (FLAG_preparser_scope_analysis) {
+ if (FLAG_experimental_preparser_scope_analysis) {
Variable* var = LookupLocal(name);
DCHECK_NE(var, kDummyPreParserLexicalVariable);
DCHECK_NE(var, kDummyPreParserVariable);
@@ -1332,7 +1332,7 @@ Declaration* Scope::CheckLexDeclarationsConflictingWith(
void DeclarationScope::AllocateVariables(ParseInfo* info, Isolate* isolate,
AnalyzeMode mode) {
// Module variables must be allocated before variable resolution
- // to ensure that AccessNeedsHoleCheck() can detect import variables.
+ // to ensure that UpdateNeedsHoleCheck() can detect import variables.
if (is_module_scope()) AsModuleScope()->AllocateModuleVariables();
ResolveVariablesRecursively(info);
@@ -1371,9 +1371,10 @@ bool Scope::AllowsLazyParsingWithoutUnresolvedVariables(
if (s->is_catch_scope()) continue;
// With scopes do not introduce variables that need allocation.
if (s->is_with_scope()) continue;
- // If everything is guaranteed to be context allocated we can ignore the
- // scope.
- if (s->has_forced_context_allocation()) continue;
+ // Module scopes context-allocate all variables, and have no
+ // {this} or {arguments} variables whose existence depends on
+ // references to them.
+ if (s->is_module_scope()) continue;
// Only block scopes and function scopes should disallow preparsing.
DCHECK(s->is_block_scope() || s->is_function_scope());
return false;
@@ -1407,19 +1408,6 @@ int Scope::ContextChainLengthUntilOutermostSloppyEval() const {
return result;
}
-int Scope::MaxNestedContextChainLength() {
- int max_context_chain_length = 0;
- for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
- if (scope->is_function_scope()) continue;
- max_context_chain_length = std::max(scope->MaxNestedContextChainLength(),
- max_context_chain_length);
- }
- if (NeedsContext()) {
- max_context_chain_length += 1;
- }
- return max_context_chain_length;
-}
-
DeclarationScope* Scope::GetDeclarationScope() {
Scope* scope = this;
while (!scope->is_declaration_scope()) {
@@ -1506,6 +1494,7 @@ void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory,
inner_scope_ = nullptr;
unresolved_ = nullptr;
sloppy_block_function_map_ = nullptr;
+ rare_data_ = nullptr;
if (aborted) {
// Prepare scope for use in the outer zone.
@@ -1552,7 +1541,8 @@ void DeclarationScope::AnalyzePartially(
arguments_ = nullptr;
}
- if (FLAG_preparser_scope_analysis && preparsed_scope_data->Producing()) {
+ if (FLAG_experimental_preparser_scope_analysis &&
+ preparsed_scope_data->Producing()) {
// Store the information needed for allocating the locals of this scope
// and its inner scopes.
preparsed_scope_data->SaveData(this);
@@ -1639,6 +1629,12 @@ void PrintVar(int indent, Variable* var) {
if (var->maybe_assigned() == kNotAssigned) {
if (comma) PrintF(", ");
PrintF("never assigned");
+ comma = true;
+ }
+ if (var->initialization_flag() == kNeedsInitialization &&
+ !var->binding_needs_init()) {
+ if (comma) PrintF(", ");
+ PrintF("hole initialization elided");
}
PrintF("\n");
}
@@ -1798,7 +1794,9 @@ void Scope::CheckZones() {
DCHECK_NULL(scope->inner_scope_);
continue;
}
- CHECK_EQ(scope->zone(), zone());
+ if (!scope->replaced_from_parse_task()) {
+ CHECK_EQ(scope->zone(), zone());
+ }
scope->CheckZones();
}
}
@@ -1910,25 +1908,28 @@ void Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy) {
namespace {
-bool AccessNeedsHoleCheck(Variable* var, VariableProxy* proxy, Scope* scope) {
+void SetNeedsHoleCheck(Variable* var, VariableProxy* proxy) {
+ proxy->set_needs_hole_check();
+ var->ForceHoleInitialization();
+}
+
+void UpdateNeedsHoleCheck(Variable* var, VariableProxy* proxy, Scope* scope) {
if (var->mode() == DYNAMIC_LOCAL) {
// Dynamically introduced variables never need a hole check (since they're
// VAR bindings, either from var or function declarations), but the variable
// they shadow might need a hole check, which we want to do if we decide
// that no shadowing variable was dynamically introoduced.
- DCHECK(!var->binding_needs_init());
- return AccessNeedsHoleCheck(var->local_if_not_shadowed(), proxy, scope);
+ DCHECK_EQ(kCreatedInitialized, var->initialization_flag());
+ return UpdateNeedsHoleCheck(var->local_if_not_shadowed(), proxy, scope);
}
- if (!var->binding_needs_init()) {
- return false;
- }
+ if (var->initialization_flag() == kCreatedInitialized) return;
// It's impossible to eliminate module import hole checks here, because it's
// unknown at compilation time whether the binding referred to in the
// exporting module itself requires hole checks.
if (var->location() == VariableLocation::MODULE && !var->IsExport()) {
- return true;
+ return SetNeedsHoleCheck(var, proxy);
}
// Check if the binding really needs an initialization check. The check
@@ -1939,7 +1940,7 @@ bool AccessNeedsHoleCheck(Variable* var, VariableProxy* proxy, Scope* scope) {
// the source physically located after the initializer of the variable,
// and that the initializer cannot be skipped due to a nonlinear scope.
//
- // The condition on the declaration scopes is a conservative check for
+ // The condition on the closure scopes is a conservative check for
// nested functions that access a binding and are called before the
// binding is initialized:
// function() { f(); let x = 1; function f() { x = 2; } }
@@ -1949,22 +1950,24 @@ bool AccessNeedsHoleCheck(Variable* var, VariableProxy* proxy, Scope* scope) {
// switch (1) { case 0: let x = 2; case 1: f(x); }
// The scope of the variable needs to be checked, in case the use is
// in a sub-block which may be linear.
- if (var->scope()->GetDeclarationScope() != scope->GetDeclarationScope()) {
- return true;
+ if (var->scope()->GetClosureScope() != scope->GetClosureScope()) {
+ return SetNeedsHoleCheck(var, proxy);
}
if (var->is_this()) {
- DCHECK(IsDerivedConstructor(scope->GetDeclarationScope()->function_kind()));
+ DCHECK(IsDerivedConstructor(scope->GetClosureScope()->function_kind()));
// TODO(littledan): implement 'this' hole check elimination.
- return true;
+ return SetNeedsHoleCheck(var, proxy);
}
// We should always have valid source positions.
DCHECK(var->initializer_position() != kNoSourcePosition);
DCHECK(proxy->position() != kNoSourcePosition);
- return var->scope()->is_nonlinear() ||
- var->initializer_position() >= proxy->position();
+ if (var->scope()->is_nonlinear() ||
+ var->initializer_position() >= proxy->position()) {
+ return SetNeedsHoleCheck(var, proxy);
+ }
}
} // anonymous namespace
@@ -1992,7 +1995,7 @@ void Scope::ResolveTo(ParseInfo* info, VariableProxy* proxy, Variable* var) {
#endif
DCHECK_NOT_NULL(var);
- if (AccessNeedsHoleCheck(var, proxy, this)) proxy->set_needs_hole_check();
+ UpdateNeedsHoleCheck(var, proxy, this);
proxy->BindTo(var);
}
@@ -2031,7 +2034,7 @@ VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope,
ParseInfo* info,
VariableProxy* stack) {
// Module variables must be allocated before variable resolution
- // to ensure that AccessNeedsHoleCheck() can detect import variables.
+ // to ensure that UpdateNeedsHoleCheck() can detect import variables.
if (info != nullptr && is_module_scope()) {
AsModuleScope()->AllocateModuleVariables();
}
@@ -2257,7 +2260,8 @@ void ModuleScope::AllocateModuleVariables() {
void Scope::AllocateVariablesRecursively() {
DCHECK(!already_resolved_);
- DCHECK_IMPLIES(!FLAG_preparser_scope_analysis, num_stack_slots_ == 0);
+ DCHECK_IMPLIES(!FLAG_experimental_preparser_scope_analysis,
+ num_stack_slots_ == 0);
// Don't allocate variables of preparsed scopes.
if (is_declaration_scope() && AsDeclarationScope()->was_lazily_parsed()) {
diff --git a/deps/v8/src/ast/scopes.h b/deps/v8/src/ast/scopes.h
index c7de9e88ee..35c0bb0b2d 100644
--- a/deps/v8/src/ast/scopes.h
+++ b/deps/v8/src/ast/scopes.h
@@ -400,10 +400,6 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
// sloppy eval call. One if this->calls_sloppy_eval().
int ContextChainLengthUntilOutermostSloppyEval() const;
- // The maximum number of nested contexts required for this scope and any inner
- // scopes.
- int MaxNestedContextChainLength();
-
// Find the first function, script, eval or (declaration) block scope. This is
// the scope where var declarations will be hoisted to in the implementation.
DeclarationScope* GetDeclarationScope();
@@ -456,6 +452,11 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
// Check that all Scopes in the scope tree use the same Zone.
void CheckZones();
+
+ bool replaced_from_parse_task() const { return replaced_from_parse_task_; }
+ void set_replaced_from_parse_task(bool replaced_from_parse_task) {
+ replaced_from_parse_task_ = replaced_from_parse_task;
+ }
#endif
// Retrieve `IsSimpleParameterList` of current or outer function.
@@ -535,6 +536,10 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
// True if this scope may contain objects from a temp zone that needs to be
// fixed up.
bool needs_migration_;
+
+ // True if scope comes from other zone - as a result of being created in a
+ // parse tasks.
+ bool replaced_from_parse_task_ = false;
#endif
// Source positions.
@@ -651,7 +656,12 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
}
// Inform the scope that the corresponding code uses "super".
- void RecordSuperPropertyUsage() { scope_uses_super_property_ = true; }
+ void RecordSuperPropertyUsage() {
+ DCHECK((IsConciseMethod(function_kind()) ||
+ IsAccessorFunction(function_kind()) ||
+ IsClassConstructor(function_kind())));
+ scope_uses_super_property_ = true;
+ }
// Does this scope access "super" property (super.foo).
bool uses_super_property() const { return scope_uses_super_property_; }
diff --git a/deps/v8/src/ast/variables.cc b/deps/v8/src/ast/variables.cc
index cd1d8f77b7..c6611bd0d9 100644
--- a/deps/v8/src/ast/variables.cc
+++ b/deps/v8/src/ast/variables.cc
@@ -27,6 +27,7 @@ Variable::Variable(Scope* scope, const AstRawString* name, VariableMode mode,
InitializationFlagField::encode(initialization_flag) |
VariableModeField::encode(mode) | IsUsedField::encode(false) |
ForceContextAllocationField::encode(false) |
+ ForceHoleInitializationField::encode(false) |
LocationField::encode(VariableLocation::UNALLOCATED) |
VariableKindField::encode(kind)) {
// Var declared variables never need initialization.
diff --git a/deps/v8/src/ast/variables.h b/deps/v8/src/ast/variables.h
index 3eaa105168..c01db36274 100644
--- a/deps/v8/src/ast/variables.h
+++ b/deps/v8/src/ast/variables.h
@@ -66,11 +66,47 @@ class Variable final : public ZoneObject {
bool IsGlobalObjectProperty() const;
bool is_dynamic() const { return IsDynamicVariableMode(mode()); }
+
+ // Returns the InitializationFlag this Variable was created with.
+ // Scope analysis may allow us to relax this initialization
+ // requirement, which will be reflected in the return value of
+ // binding_needs_init().
+ InitializationFlag initialization_flag() const {
+ return InitializationFlagField::decode(bit_field_);
+ }
+
+ // Whether this variable needs to be initialized with the hole at
+ // declaration time. Only returns valid results after scope analysis.
bool binding_needs_init() const {
- DCHECK(initialization_flag() != kNeedsInitialization ||
- IsLexicalVariableMode(mode()));
+ DCHECK_IMPLIES(initialization_flag() == kNeedsInitialization,
+ IsLexicalVariableMode(mode()));
+ DCHECK_IMPLIES(ForceHoleInitializationField::decode(bit_field_),
+ initialization_flag() == kNeedsInitialization);
+
+ // Always initialize if hole initialization was forced during
+ // scope analysis.
+ if (ForceHoleInitializationField::decode(bit_field_)) return true;
+
+ // If initialization was not forced, no need for initialization
+ // for stack allocated variables, since UpdateNeedsHoleCheck()
+ // in scopes.cc has proven that no VariableProxy refers to
+ // this variable in such a way that a runtime hole check
+ // would be generated.
+ if (IsStackAllocated()) return false;
+
+ // Otherwise, defer to the flag set when this Variable was constructed.
return initialization_flag() == kNeedsInitialization;
}
+
+ // Called during scope analysis when a VariableProxy is found to
+ // reference this Variable in such a way that a hole check will
+ // be required at runtime.
+ void ForceHoleInitialization() {
+ DCHECK_EQ(kNeedsInitialization, initialization_flag());
+ DCHECK(IsLexicalVariableMode(mode()));
+ bit_field_ = ForceHoleInitializationField::update(bit_field_, true);
+ }
+
bool throw_on_const_assignment(LanguageMode language_mode) const {
return kind() != SLOPPY_FUNCTION_NAME_VARIABLE || is_strict(language_mode);
}
@@ -94,9 +130,6 @@ class Variable final : public ZoneObject {
return LocationField::decode(bit_field_);
}
VariableKind kind() const { return VariableKindField::decode(bit_field_); }
- InitializationFlag initialization_flag() const {
- return InitializationFlagField::decode(bit_field_);
- }
int index() const { return index_; }
@@ -152,10 +185,12 @@ class Variable final : public ZoneObject {
class IsUsedField
: public BitField16<bool, ForceContextAllocationField::kNext, 1> {};
class InitializationFlagField
- : public BitField16<InitializationFlag, IsUsedField::kNext, 2> {};
+ : public BitField16<InitializationFlag, IsUsedField::kNext, 1> {};
+ class ForceHoleInitializationField
+ : public BitField16<bool, InitializationFlagField::kNext, 1> {};
class MaybeAssignedFlagField
- : public BitField16<MaybeAssignedFlag, InitializationFlagField::kNext,
- 2> {};
+ : public BitField16<MaybeAssignedFlag,
+ ForceHoleInitializationField::kNext, 1> {};
Variable** next() { return &next_; }
friend List;
};