diff options
Diffstat (limited to 'chromium/v8/src/ast')
-rw-r--r-- | chromium/v8/src/ast/ast-function-literal-id-reindexer.cc | 4 | ||||
-rw-r--r-- | chromium/v8/src/ast/ast-function-literal-id-reindexer.h | 5 | ||||
-rw-r--r-- | chromium/v8/src/ast/ast-source-ranges.h | 19 | ||||
-rw-r--r-- | chromium/v8/src/ast/ast-traversal-visitor.h | 37 | ||||
-rw-r--r-- | chromium/v8/src/ast/ast-value-factory.cc | 128 | ||||
-rw-r--r-- | chromium/v8/src/ast/ast-value-factory.h | 137 | ||||
-rw-r--r-- | chromium/v8/src/ast/ast.cc | 16 | ||||
-rw-r--r-- | chromium/v8/src/ast/ast.h | 216 | ||||
-rw-r--r-- | chromium/v8/src/ast/modules.cc | 52 | ||||
-rw-r--r-- | chromium/v8/src/ast/modules.h | 46 | ||||
-rw-r--r-- | chromium/v8/src/ast/prettyprinter.cc | 104 | ||||
-rw-r--r-- | chromium/v8/src/ast/prettyprinter.h | 3 | ||||
-rw-r--r-- | chromium/v8/src/ast/scopes.cc | 115 | ||||
-rw-r--r-- | chromium/v8/src/ast/scopes.h | 65 |
14 files changed, 619 insertions, 328 deletions
diff --git a/chromium/v8/src/ast/ast-function-literal-id-reindexer.cc b/chromium/v8/src/ast/ast-function-literal-id-reindexer.cc index 8c9318bfe74..298e9ea14f7 100644 --- a/chromium/v8/src/ast/ast-function-literal-id-reindexer.cc +++ b/chromium/v8/src/ast/ast-function-literal-id-reindexer.cc @@ -40,8 +40,8 @@ void AstFunctionLiteralIdReindexer::VisitClassLiteral(ClassLiteral* expr) { Visit(expr->extends()); } Visit(expr->constructor()); - if (expr->static_fields_initializer() != nullptr) { - Visit(expr->static_fields_initializer()); + if (expr->static_initializer() != nullptr) { + Visit(expr->static_initializer()); } if (expr->instance_members_initializer_function() != nullptr) { Visit(expr->instance_members_initializer_function()); diff --git a/chromium/v8/src/ast/ast-function-literal-id-reindexer.h b/chromium/v8/src/ast/ast-function-literal-id-reindexer.h index f4dac7b01e6..2c1eb108afd 100644 --- a/chromium/v8/src/ast/ast-function-literal-id-reindexer.h +++ b/chromium/v8/src/ast/ast-function-literal-id-reindexer.h @@ -21,6 +21,9 @@ class AstFunctionLiteralIdReindexer final : public AstTraversalVisitor<AstFunctionLiteralIdReindexer> { public: AstFunctionLiteralIdReindexer(size_t stack_limit, int delta); + AstFunctionLiteralIdReindexer(const AstFunctionLiteralIdReindexer&) = delete; + AstFunctionLiteralIdReindexer& operator=( + const AstFunctionLiteralIdReindexer&) = delete; ~AstFunctionLiteralIdReindexer(); void Reindex(Expression* pattern); @@ -42,8 +45,6 @@ class AstFunctionLiteralIdReindexer final #else void CheckVisited(Expression* expr) {} #endif - - DISALLOW_COPY_AND_ASSIGN(AstFunctionLiteralIdReindexer); }; } // namespace internal diff --git a/chromium/v8/src/ast/ast-source-ranges.h b/chromium/v8/src/ast/ast-source-ranges.h index 1b42a055dd6..1e96ec4c27c 100644 --- a/chromium/v8/src/ast/ast-source-ranges.h +++ b/chromium/v8/src/ast/ast-source-ranges.h @@ -47,6 +47,7 @@ struct SourceRange { V(Block) \ V(CaseClause) \ V(Conditional) \ + V(Expression) \ V(FunctionLiteral) \ V(IfStatement) \ V(IterationStatement) \ @@ -281,6 +282,24 @@ class NaryOperationSourceRanges final : public AstNodeSourceRanges { ZoneVector<SourceRange> ranges_; }; +class ExpressionSourceRanges final : public AstNodeSourceRanges { + public: + explicit ExpressionSourceRanges(const SourceRange& right_range) + : right_range_(right_range) {} + + SourceRange GetRange(SourceRangeKind kind) override { + DCHECK(HasRange(kind)); + return right_range_; + } + + bool HasRange(SourceRangeKind kind) override { + return kind == SourceRangeKind::kRight; + } + + private: + SourceRange right_range_; +}; + class SuspendSourceRanges final : public ContinuationSourceRanges { public: explicit SuspendSourceRanges(int32_t continuation_position) diff --git a/chromium/v8/src/ast/ast-traversal-visitor.h b/chromium/v8/src/ast/ast-traversal-visitor.h index 8a1f8b2f16e..a9e3500931a 100644 --- a/chromium/v8/src/ast/ast-traversal-visitor.h +++ b/chromium/v8/src/ast/ast-traversal-visitor.h @@ -30,6 +30,8 @@ class AstTraversalVisitor : public AstVisitor<Subclass> { public: explicit AstTraversalVisitor(Isolate* isolate, AstNode* root = nullptr); explicit AstTraversalVisitor(uintptr_t stack_limit, AstNode* root = nullptr); + AstTraversalVisitor(const AstTraversalVisitor&) = delete; + AstTraversalVisitor& operator=(const AstTraversalVisitor&) = delete; void Run() { DCHECK_NOT_NULL(root_); @@ -56,8 +58,6 @@ class AstTraversalVisitor : public AstVisitor<Subclass> { AstNode* root_; int depth_; - - DISALLOW_COPY_AND_ASSIGN(AstTraversalVisitor); }; // ---------------------------------------------------------------------------- @@ -469,8 +469,8 @@ void AstTraversalVisitor<Subclass>::VisitClassLiteral(ClassLiteral* expr) { RECURSE_EXPRESSION(Visit(expr->extends())); } RECURSE_EXPRESSION(Visit(expr->constructor())); - if (expr->static_fields_initializer() != nullptr) { - RECURSE_EXPRESSION(Visit(expr->static_fields_initializer())); + if (expr->static_initializer() != nullptr) { + RECURSE_EXPRESSION(Visit(expr->static_initializer())); } if (expr->instance_members_initializer_function() != nullptr) { RECURSE_EXPRESSION(Visit(expr->instance_members_initializer_function())); @@ -506,6 +506,29 @@ void AstTraversalVisitor<Subclass>::VisitInitializeClassMembersStatement( } template <class Subclass> +void AstTraversalVisitor<Subclass>::VisitInitializeClassStaticElementsStatement( + InitializeClassStaticElementsStatement* stmt) { + PROCESS_NODE(stmt); + ZonePtrList<ClassLiteral::StaticElement>* elements = stmt->elements(); + for (int i = 0; i < elements->length(); ++i) { + ClassLiteral::StaticElement* element = elements->at(i); + switch (element->kind()) { + case ClassLiteral::StaticElement::PROPERTY: { + ClassLiteral::Property* prop = element->property(); + if (!prop->key()->IsLiteral()) { + RECURSE(Visit(prop->key())); + } + RECURSE(Visit(prop->value())); + break; + } + case ClassLiteral::StaticElement::STATIC_BLOCK: + RECURSE(Visit(element->static_block())); + break; + } + } +} + +template <class Subclass> void AstTraversalVisitor<Subclass>::VisitSpread(Spread* expr) { PROCESS_EXPRESSION(expr); RECURSE_EXPRESSION(Visit(expr->expression())); @@ -536,14 +559,16 @@ template <class Subclass> void AstTraversalVisitor<Subclass>::VisitImportCallExpression( ImportCallExpression* expr) { PROCESS_EXPRESSION(expr); - RECURSE_EXPRESSION(Visit(expr->argument())); + RECURSE_EXPRESSION(Visit(expr->specifier())); + if (expr->import_assertions()) { + RECURSE_EXPRESSION(Visit(expr->import_assertions())); + } } template <class Subclass> void AstTraversalVisitor<Subclass>::VisitSuperPropertyReference( SuperPropertyReference* expr) { PROCESS_EXPRESSION(expr); - RECURSE_EXPRESSION(Visit(expr->home_object())); } template <class Subclass> diff --git a/chromium/v8/src/ast/ast-value-factory.cc b/chromium/v8/src/ast/ast-value-factory.cc index b5a39b22cf3..6e454b22f1d 100644 --- a/chromium/v8/src/ast/ast-value-factory.cc +++ b/chromium/v8/src/ast/ast-value-factory.cc @@ -29,6 +29,7 @@ #include "src/base/hashmap-entry.h" #include "src/base/logging.h" +#include "src/base/platform/wrappers.h" #include "src/common/globals.h" #include "src/heap/factory-inl.h" #include "src/heap/local-factory-inl.h" @@ -66,10 +67,10 @@ void AstRawString::Internalize(LocalIsolate* isolate) { if (literal_bytes_.length() == 0) { set_string(isolate->factory()->empty_string()); } else if (is_one_byte()) { - OneByteStringKey key(hash_field_, literal_bytes_); + OneByteStringKey key(raw_hash_field_, literal_bytes_); set_string(isolate->factory()->InternalizeStringWithKey(&key)); } else { - TwoByteStringKey key(hash_field_, + TwoByteStringKey key(raw_hash_field_, Vector<const uint16_t>::cast(literal_bytes_)); set_string(isolate->factory()->InternalizeStringWithKey(&key)); } @@ -83,9 +84,9 @@ template EXPORT_TEMPLATE_DEFINE( bool AstRawString::AsArrayIndex(uint32_t* index) const { // The StringHasher will set up the hash. Bail out early if we know it // can't be convertible to an array index. - if ((hash_field_ & Name::kIsNotIntegerIndexMask) != 0) return false; + if ((raw_hash_field_ & Name::kIsNotIntegerIndexMask) != 0) return false; if (length() <= Name::kMaxCachedArrayIndexLength) { - *index = Name::ArrayIndexValueBits::decode(hash_field_); + *index = Name::ArrayIndexValueBits::decode(raw_hash_field_); return true; } // Might be an index, but too big to cache it. Do the slow conversion. This @@ -96,7 +97,7 @@ bool AstRawString::AsArrayIndex(uint32_t* index) const { } bool AstRawString::IsIntegerIndex() const { - return (hash_field_ & Name::kIsNotIntegerIndexMask) == 0; + return (raw_hash_field_ & Name::kIsNotIntegerIndexMask) == 0; } bool AstRawString::IsOneByteEqualTo(const char* data) const { @@ -115,7 +116,7 @@ uint16_t AstRawString::FirstCharacter() const { return *c; } -bool AstRawString::Compare(const AstRawString* lhs, const AstRawString* rhs) { +bool AstRawString::Equal(const AstRawString* lhs, const AstRawString* rhs) { DCHECK_EQ(lhs->Hash(), rhs->Hash()); if (lhs->length() != rhs->length()) return false; @@ -125,27 +126,65 @@ bool AstRawString::Compare(const AstRawString* lhs, const AstRawString* rhs) { size_t length = rhs->length(); if (lhs->is_one_byte()) { if (rhs->is_one_byte()) { - return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l), - reinterpret_cast<const uint8_t*>(r), - length) == 0; + return CompareCharsEqualUnsigned(reinterpret_cast<const uint8_t*>(l), + reinterpret_cast<const uint8_t*>(r), + length); } else { - return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l), - reinterpret_cast<const uint16_t*>(r), - length) == 0; + return CompareCharsEqualUnsigned(reinterpret_cast<const uint8_t*>(l), + reinterpret_cast<const uint16_t*>(r), + length); } } else { if (rhs->is_one_byte()) { - return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l), - reinterpret_cast<const uint8_t*>(r), - length) == 0; + return CompareCharsEqualUnsigned(reinterpret_cast<const uint16_t*>(l), + reinterpret_cast<const uint8_t*>(r), + length); } else { - return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l), - reinterpret_cast<const uint16_t*>(r), - length) == 0; + return CompareCharsEqualUnsigned(reinterpret_cast<const uint16_t*>(l), + reinterpret_cast<const uint16_t*>(r), + length); } } } +int AstRawString::Compare(const AstRawString* lhs, const AstRawString* rhs) { + // Fast path for equal pointers. + if (lhs == rhs) return 0; + + const unsigned char* lhs_data = lhs->raw_data(); + const unsigned char* rhs_data = rhs->raw_data(); + size_t length = std::min(lhs->length(), rhs->length()); + + // Code point order by contents. + if (lhs->is_one_byte()) { + if (rhs->is_one_byte()) { + if (int result = CompareCharsUnsigned( + reinterpret_cast<const uint8_t*>(lhs_data), + reinterpret_cast<const uint8_t*>(rhs_data), length)) + return result; + } else { + if (int result = CompareCharsUnsigned( + reinterpret_cast<const uint8_t*>(lhs_data), + reinterpret_cast<const uint16_t*>(rhs_data), length)) + return result; + } + } else { + if (rhs->is_one_byte()) { + if (int result = CompareCharsUnsigned( + reinterpret_cast<const uint16_t*>(lhs_data), + reinterpret_cast<const uint8_t*>(rhs_data), length)) + return result; + } else { + if (int result = CompareCharsUnsigned( + reinterpret_cast<const uint16_t*>(lhs_data), + reinterpret_cast<const uint16_t*>(rhs_data), length)) + return result; + } + } + + return lhs->byte_length() - rhs->byte_length(); +} + template <typename LocalIsolate> Handle<String> AstConsString::Allocate(LocalIsolate* isolate) const { DCHECK(string_.is_null()); @@ -193,7 +232,7 @@ Handle<String> AstConsString::AllocateFlat(LocalIsolate* isolate) const { isolate->factory() ->NewRawOneByteString(result_length, AllocationType::kOld) .ToHandleChecked(); - DisallowHeapAllocation no_gc; + DisallowGarbageCollection no_gc; uint8_t* dest = result->GetChars(no_gc, SharedStringAccessGuardIfNeeded::NotNeeded()) + result_length; @@ -212,7 +251,7 @@ Handle<String> AstConsString::AllocateFlat(LocalIsolate* isolate) const { isolate->factory() ->NewRawTwoByteString(result_length, AllocationType::kOld) .ToHandleChecked(); - DisallowHeapAllocation no_gc; + DisallowGarbageCollection no_gc; uint16_t* dest = result->GetChars(no_gc, SharedStringAccessGuardIfNeeded::NotNeeded()) + result_length; @@ -257,18 +296,18 @@ AstStringConstants::AstStringConstants(Isolate* isolate, uint64_t hash_seed) string_table_(), hash_seed_(hash_seed) { DCHECK_EQ(ThreadId::Current(), isolate->thread_id()); -#define F(name, str) \ - { \ - const char* data = str; \ - Vector<const uint8_t> literal(reinterpret_cast<const uint8_t*>(data), \ - static_cast<int>(strlen(data))); \ - uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>( \ - literal.begin(), literal.length(), hash_seed_); \ - name##_string_ = zone_.New<AstRawString>(true, literal, hash_field); \ - /* The Handle returned by the factory is located on the roots */ \ - /* array, not on the temporary HandleScope, so this is safe. */ \ - name##_string_->set_string(isolate->factory()->name##_string()); \ - string_table_.InsertNew(name##_string_, name##_string_->Hash()); \ +#define F(name, str) \ + { \ + const char* data = str; \ + Vector<const uint8_t> literal(reinterpret_cast<const uint8_t*>(data), \ + static_cast<int>(strlen(data))); \ + uint32_t raw_hash_field = StringHasher::HashSequentialString<uint8_t>( \ + literal.begin(), literal.length(), hash_seed_); \ + name##_string_ = zone_.New<AstRawString>(true, literal, raw_hash_field); \ + /* The Handle returned by the factory is located on the roots */ \ + /* array, not on the temporary HandleScope, so this is safe. */ \ + name##_string_->set_string(isolate->factory()->name##_string()); \ + string_table_.InsertNew(name##_string_, name##_string_->Hash()); \ } AST_STRING_CONSTANTS(F) #undef F @@ -279,27 +318,27 @@ const AstRawString* AstValueFactory::GetOneByteStringInternal( if (literal.length() == 1 && literal[0] < kMaxOneCharStringValue) { int key = literal[0]; if (V8_UNLIKELY(one_character_strings_[key] == nullptr)) { - uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>( + uint32_t raw_hash_field = StringHasher::HashSequentialString<uint8_t>( literal.begin(), literal.length(), hash_seed_); - one_character_strings_[key] = GetString(hash_field, true, literal); + one_character_strings_[key] = GetString(raw_hash_field, true, literal); } return one_character_strings_[key]; } - uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>( + uint32_t raw_hash_field = StringHasher::HashSequentialString<uint8_t>( literal.begin(), literal.length(), hash_seed_); - return GetString(hash_field, true, literal); + return GetString(raw_hash_field, true, literal); } const AstRawString* AstValueFactory::GetTwoByteStringInternal( Vector<const uint16_t> literal) { - uint32_t hash_field = StringHasher::HashSequentialString<uint16_t>( + uint32_t raw_hash_field = StringHasher::HashSequentialString<uint16_t>( literal.begin(), literal.length(), hash_seed_); - return GetString(hash_field, false, Vector<const byte>::cast(literal)); + return GetString(raw_hash_field, false, Vector<const byte>::cast(literal)); } const AstRawString* AstValueFactory::GetString(Handle<String> literal) { const AstRawString* result = nullptr; - DisallowHeapAllocation no_gc; + DisallowGarbageCollection no_gc; String::FlatContent content = literal->GetFlatContent(no_gc); if (content.IsOneByte()) { result = GetOneByteStringInternal(content.ToOneByteVector()); @@ -313,7 +352,7 @@ const AstRawString* AstValueFactory::GetString(Handle<String> literal) { const AstRawString* AstValueFactory::CloneFromOtherFactory( const AstRawString* raw_string) { const AstRawString* result = GetString( - raw_string->hash_field(), raw_string->is_one_byte(), + raw_string->raw_hash_field(), raw_string->is_one_byte(), Vector<const byte>(raw_string->raw_data(), raw_string->byte_length())); return result; } @@ -352,22 +391,23 @@ template EXPORT_TEMPLATE_DEFINE( V8_EXPORT_PRIVATE) void AstValueFactory::Internalize(LocalIsolate* isolate); const AstRawString* AstValueFactory::GetString( - uint32_t hash_field, bool is_one_byte, Vector<const byte> literal_bytes) { + uint32_t raw_hash_field, bool is_one_byte, + Vector<const byte> literal_bytes) { // literal_bytes here points to whatever the user passed, and this is OK // because we use vector_compare (which checks the contents) to compare // against the AstRawStrings which are in the string_table_. We should not // return this AstRawString. - AstRawString key(is_one_byte, literal_bytes, hash_field); + AstRawString key(is_one_byte, literal_bytes, raw_hash_field); AstRawStringMap::Entry* entry = string_table_.LookupOrInsert( &key, key.Hash(), [&]() { // Copy literal contents for later comparison. int length = literal_bytes.length(); byte* new_literal_bytes = zone()->NewArray<byte>(length); - memcpy(new_literal_bytes, literal_bytes.begin(), length); + base::Memcpy(new_literal_bytes, literal_bytes.begin(), length); AstRawString* new_string = zone()->New<AstRawString>( is_one_byte, Vector<const byte>(new_literal_bytes, length), - hash_field); + raw_hash_field); CHECK_NOT_NULL(new_string); AddString(new_string); return new_string; diff --git a/chromium/v8/src/ast/ast-value-factory.h b/chromium/v8/src/ast/ast-value-factory.h index 776b45a670e..b66e11f99fa 100644 --- a/chromium/v8/src/ast/ast-value-factory.h +++ b/chromium/v8/src/ast/ast-value-factory.h @@ -48,7 +48,12 @@ class Isolate; class AstRawString final : public ZoneObject { public: - static bool Compare(const AstRawString* a, const AstRawString* b); + static bool Equal(const AstRawString* lhs, const AstRawString* rhs); + + // Returns 0 if lhs is equal to rhs. + // Returns <0 if lhs is less than rhs in code point order. + // Returns >0 if lhs is greater than than rhs in code point order. + static int Compare(const AstRawString* lhs, const AstRawString* rhs); bool IsEmpty() const { return literal_bytes_.length() == 0; } int length() const { @@ -71,8 +76,12 @@ class AstRawString final : public ZoneObject { bool IsPrivateName() const { return length() > 0 && FirstCharacter() == '#'; } // For storing AstRawStrings in a hash map. - uint32_t hash_field() const { return hash_field_; } - uint32_t Hash() const { return hash_field_ >> Name::kHashShift; } + uint32_t raw_hash_field() const { return raw_hash_field_; } + uint32_t Hash() const { + // Hash field must be computed. + DCHECK_EQ(raw_hash_field_ & Name::kHashNotComputedMask, 0); + return raw_hash_field_ >> Name::kHashShift; + } // This function can be called after internalizing. V8_INLINE Handle<String> string() const { @@ -88,10 +97,10 @@ class AstRawString final : public ZoneObject { // Members accessed only by the AstValueFactory & related classes: AstRawString(bool is_one_byte, const Vector<const byte>& literal_bytes, - uint32_t hash_field) + uint32_t raw_hash_field) : next_(nullptr), literal_bytes_(literal_bytes), - hash_field_(hash_field), + raw_hash_field_(raw_hash_field), is_one_byte_(is_one_byte) {} AstRawString* next() { DCHECK(!has_string_); @@ -117,7 +126,7 @@ class AstRawString final : public ZoneObject { }; Vector<const byte> literal_bytes_; // Memory owned by Zone. - uint32_t hash_field_; + uint32_t raw_hash_field_; bool is_one_byte_; #ifdef DEBUG // (Debug-only:) Verify the object life-cylce: Some functions may only be @@ -191,8 +200,6 @@ class AstConsString final : public ZoneObject { Segment segment_; }; -enum class AstSymbol : uint8_t { kHomeObjectSymbol }; - class AstBigInt { public: // |bigint| must be a NUL-terminated string of ASCII characters @@ -210,7 +217,7 @@ struct AstRawStringMapMatcher { bool operator()(uint32_t hash1, uint32_t hash2, const AstRawString* lookup_key, const AstRawString* entry_key) const { - return hash1 == hash2 && AstRawString::Compare(lookup_key, entry_key); + return hash1 == hash2 && AstRawString::Equal(lookup_key, entry_key); } }; @@ -220,63 +227,67 @@ using AstRawStringMap = base::DefaultAllocationPolicy>; // For generating constants. -#define AST_STRING_CONSTANTS(F) \ - F(anonymous, "anonymous") \ - F(anonymous_function, "(anonymous function)") \ - F(arguments, "arguments") \ - F(as, "as") \ - F(assert, "assert") \ - F(async, "async") \ - F(await, "await") \ - F(bigint, "bigint") \ - F(boolean, "boolean") \ - F(computed, "<computed>") \ - F(dot_brand, ".brand") \ - F(constructor, "constructor") \ - F(default, "default") \ - F(done, "done") \ - F(dot, ".") \ - F(dot_default, ".default") \ - F(dot_for, ".for") \ - F(dot_generator_object, ".generator_object") \ - F(dot_result, ".result") \ - F(dot_repl_result, ".repl_result") \ - F(dot_switch_tag, ".switch_tag") \ - F(dot_catch, ".catch") \ - F(empty, "") \ - F(eval, "eval") \ - F(from, "from") \ - F(function, "function") \ - F(get, "get") \ - F(get_space, "get ") \ - F(length, "length") \ - F(let, "let") \ - F(meta, "meta") \ - F(name, "name") \ - F(native, "native") \ - F(new_target, ".new.target") \ - F(next, "next") \ - F(number, "number") \ - F(object, "object") \ - F(of, "of") \ - F(private_constructor, "#constructor") \ - F(proto, "__proto__") \ - F(prototype, "prototype") \ - F(return, "return") \ - F(set, "set") \ - F(set_space, "set ") \ - F(string, "string") \ - F(symbol, "symbol") \ - F(target, "target") \ - F(this, "this") \ - F(this_function, ".this_function") \ - F(throw, "throw") \ - F(undefined, "undefined") \ +#define AST_STRING_CONSTANTS(F) \ + F(anonymous, "anonymous") \ + F(anonymous_function, "(anonymous function)") \ + F(arguments, "arguments") \ + F(as, "as") \ + F(assert, "assert") \ + F(async, "async") \ + F(await, "await") \ + F(bigint, "bigint") \ + F(boolean, "boolean") \ + F(computed, "<computed>") \ + F(dot_brand, ".brand") \ + F(constructor, "constructor") \ + F(default, "default") \ + F(done, "done") \ + F(dot, ".") \ + F(dot_default, ".default") \ + F(dot_for, ".for") \ + F(dot_generator_object, ".generator_object") \ + F(dot_home_object, ".home_object") \ + F(dot_result, ".result") \ + F(dot_repl_result, ".repl_result") \ + F(dot_static_home_object, ".static_home_object") \ + F(dot_switch_tag, ".switch_tag") \ + F(dot_catch, ".catch") \ + F(empty, "") \ + F(eval, "eval") \ + F(from, "from") \ + F(function, "function") \ + F(get, "get") \ + F(get_space, "get ") \ + F(length, "length") \ + F(let, "let") \ + F(meta, "meta") \ + F(name, "name") \ + F(native, "native") \ + F(new_target, ".new.target") \ + F(next, "next") \ + F(number, "number") \ + F(object, "object") \ + F(of, "of") \ + F(private_constructor, "#constructor") \ + F(proto, "__proto__") \ + F(prototype, "prototype") \ + F(return, "return") \ + F(set, "set") \ + F(set_space, "set ") \ + F(string, "string") \ + F(symbol, "symbol") \ + F(target, "target") \ + F(this, "this") \ + F(this_function, ".this_function") \ + F(throw, "throw") \ + F(undefined, "undefined") \ F(value, "value") class AstStringConstants final { public: AstStringConstants(Isolate* isolate, uint64_t hash_seed); + AstStringConstants(const AstStringConstants&) = delete; + AstStringConstants& operator=(const AstStringConstants&) = delete; #define F(name, str) \ const AstRawString* name##_string() const { return name##_string_; } @@ -294,8 +305,6 @@ class AstStringConstants final { #define F(name, str) AstRawString* name##_string_; AST_STRING_CONSTANTS(F) #undef F - - DISALLOW_COPY_AND_ASSIGN(AstStringConstants); }; class AstValueFactory { @@ -369,7 +378,7 @@ class AstValueFactory { V8_EXPORT_PRIVATE const AstRawString* GetOneByteStringInternal( Vector<const uint8_t> literal); const AstRawString* GetTwoByteStringInternal(Vector<const uint16_t> literal); - const AstRawString* GetString(uint32_t hash, bool is_one_byte, + const AstRawString* GetString(uint32_t raw_hash_field, bool is_one_byte, Vector<const byte> literal_bytes); // All strings are copied here. diff --git a/chromium/v8/src/ast/ast.cc b/chromium/v8/src/ast/ast.cc index e8c7796abc2..9eddb14e613 100644 --- a/chromium/v8/src/ast/ast.cc +++ b/chromium/v8/src/ast/ast.cc @@ -11,6 +11,7 @@ #include "src/ast/scopes.h" #include "src/base/hashmap.h" #include "src/base/logging.h" +#include "src/base/platform/wrappers.h" #include "src/builtins/builtins-constructor.h" #include "src/builtins/builtins.h" #include "src/common/assert-scope.h" @@ -235,12 +236,6 @@ LanguageMode FunctionLiteral::language_mode() const { FunctionKind FunctionLiteral::kind() const { return scope()->function_kind(); } -bool FunctionLiteral::NeedsHomeObject(Expression* expr) { - if (expr == nullptr || !expr->IsFunctionLiteral()) return false; - DCHECK_NOT_NULL(expr->AsFunctionLiteral()->scope()); - return expr->AsFunctionLiteral()->scope()->NeedsHomeObject(); -} - std::unique_ptr<char[]> FunctionLiteral::GetDebugName() const { const AstConsString* cons_string; if (raw_name_ != nullptr && !raw_name_->IsEmpty()) { @@ -266,7 +261,7 @@ std::unique_ptr<char[]> FunctionLiteral::GetDebugName() const { } } std::unique_ptr<char[]> result(new char[result_vec.size() + 1]); - memcpy(result.get(), result_vec.data(), result_vec.size()); + base::Memcpy(result.get(), result_vec.data(), result_vec.size()); result[result_vec.size()] = '\0'; return result; } @@ -580,7 +575,6 @@ int ArrayLiteral::InitDepthAndFlags() { break; case Literal::kBigInt: case Literal::kString: - case Literal::kSymbol: case Literal::kBoolean: case Literal::kUndefined: case Literal::kNull: @@ -654,7 +648,7 @@ void ArrayLiteral::BuildBoilerplateDescription(LocalIsolate* isolate) { Object boilerplate_value = *GetBoilerplateValue(element, isolate); // We shouldn't allocate after creating the boilerplate value. - DisallowHeapAllocation no_gc; + DisallowGarbageCollection no_gc; if (boilerplate_value.IsTheHole(isolate)) { DCHECK(IsHoleyElementsKind(kind)); @@ -980,8 +974,6 @@ Handle<Object> Literal::BuildValue(LocalIsolate* isolate) const { number_); case kString: return string_->string(); - case kSymbol: - return isolate->factory()->home_object_symbol(); case kBoolean: return isolate->factory()->ToBoolean(boolean_); case kNull: @@ -1027,8 +1019,6 @@ bool Literal::ToBooleanIsTrue() const { } return false; } - case kSymbol: - return true; case kTheHole: UNREACHABLE(); } diff --git a/chromium/v8/src/ast/ast.h b/chromium/v8/src/ast/ast.h index 7b70181e6a0..50a0c55d4d7 100644 --- a/chromium/v8/src/ast/ast.h +++ b/chromium/v8/src/ast/ast.h @@ -54,21 +54,22 @@ namespace internal { V(Block) \ V(SwitchStatement) -#define STATEMENT_NODE_LIST(V) \ - ITERATION_NODE_LIST(V) \ - BREAKABLE_NODE_LIST(V) \ - V(ExpressionStatement) \ - V(EmptyStatement) \ - V(SloppyBlockFunctionStatement) \ - V(IfStatement) \ - V(ContinueStatement) \ - V(BreakStatement) \ - V(ReturnStatement) \ - V(WithStatement) \ - V(TryCatchStatement) \ - V(TryFinallyStatement) \ - V(DebuggerStatement) \ - V(InitializeClassMembersStatement) +#define STATEMENT_NODE_LIST(V) \ + ITERATION_NODE_LIST(V) \ + BREAKABLE_NODE_LIST(V) \ + V(ExpressionStatement) \ + V(EmptyStatement) \ + V(SloppyBlockFunctionStatement) \ + V(IfStatement) \ + V(ContinueStatement) \ + V(BreakStatement) \ + V(ReturnStatement) \ + V(WithStatement) \ + V(TryCatchStatement) \ + V(TryFinallyStatement) \ + V(DebuggerStatement) \ + V(InitializeClassMembersStatement) \ + V(InitializeClassStaticElementsStatement) #define LITERAL_NODE_LIST(V) \ V(RegExpLiteral) \ @@ -919,7 +920,6 @@ class Literal final : public Expression { kHeapNumber, kBigInt, kString, - kSymbol, kBoolean, kUndefined, kNull, @@ -974,11 +974,6 @@ class Literal final : public Expression { return string_; } - AstSymbol AsSymbol() { - DCHECK_EQ(type(), kSymbol); - return symbol_; - } - V8_EXPORT_PRIVATE bool ToBooleanIsTrue() const; bool ToBooleanIsFalse() const { return !ToBooleanIsTrue(); } @@ -1019,11 +1014,6 @@ class Literal final : public Expression { bit_field_ = TypeField::update(bit_field_, kString); } - Literal(AstSymbol symbol, int position) - : Expression(position, kLiteral), symbol_(symbol) { - bit_field_ = TypeField::update(bit_field_, kSymbol); - } - Literal(bool boolean, int position) : Expression(position, kLiteral), boolean_(boolean) { bit_field_ = TypeField::update(bit_field_, kBoolean); @@ -1038,7 +1028,6 @@ class Literal final : public Expression { const AstRawString* string_; int smi_; double number_; - AstSymbol symbol_; AstBigInt bigint_; bool boolean_; }; @@ -1307,6 +1296,8 @@ class ObjectLiteral final : public AggregateLiteral { return flags; } + Variable* home_object() const { return home_object_; } + enum Flags { kFastElements = 1 << 3, kHasNullPrototype = 1 << 4, @@ -1321,10 +1312,11 @@ class ObjectLiteral final : public AggregateLiteral { ObjectLiteral(Zone* zone, const ScopedPtrList<Property>& properties, uint32_t boilerplate_properties, int pos, - bool has_rest_property) + bool has_rest_property, Variable* home_object) : AggregateLiteral(pos, kObjectLiteral), boilerplate_properties_(boilerplate_properties), - properties_(properties.ToConstVector(), zone) { + properties_(properties.ToConstVector(), zone), + home_object_(home_object) { bit_field_ |= HasElementsField::encode(false) | HasRestPropertyField::encode(has_rest_property) | FastElementsField::encode(false) | @@ -1345,6 +1337,7 @@ class ObjectLiteral final : public AggregateLiteral { uint32_t boilerplate_properties_; Handle<ObjectBoilerplateDescription> boilerplate_description_; ZoneList<Property*> properties_; + Variable* home_object_; using HasElementsField = AggregateLiteral::NextBitField<bool, 1>; using HasRestPropertyField = HasElementsField::Next<bool, 1>; @@ -2141,8 +2134,6 @@ class FunctionLiteral final : public Expression { } V8_EXPORT_PRIVATE LanguageMode language_mode() const; - static bool NeedsHomeObject(Expression* expr); - void add_expected_properties(int number_properties) { expected_property_count_ += number_properties; } @@ -2363,11 +2354,6 @@ class ClassLiteralProperty final : public LiteralProperty { return private_or_computed_name_var_; } - bool NeedsHomeObjectOnClassPrototype() const { - return is_private() && kind_ == METHOD && - FunctionLiteral::NeedsHomeObject(value_); - } - private: friend class AstNodeFactory; friend Zone; @@ -2381,6 +2367,40 @@ class ClassLiteralProperty final : public LiteralProperty { Variable* private_or_computed_name_var_; }; +class ClassLiteralStaticElement final : public ZoneObject { + public: + enum Kind : uint8_t { PROPERTY, STATIC_BLOCK }; + + Kind kind() const { return kind_; } + + ClassLiteralProperty* property() const { + DCHECK(kind() == PROPERTY); + return property_; + } + + Block* static_block() const { + DCHECK(kind() == STATIC_BLOCK); + return static_block_; + } + + private: + friend class AstNodeFactory; + friend Zone; + + explicit ClassLiteralStaticElement(ClassLiteralProperty* property) + : kind_(PROPERTY), property_(property) {} + + explicit ClassLiteralStaticElement(Block* static_block) + : kind_(STATIC_BLOCK), static_block_(static_block) {} + + Kind kind_; + + union { + ClassLiteralProperty* property_; + Block* static_block_; + }; +}; + class InitializeClassMembersStatement final : public Statement { public: using Property = ClassLiteralProperty; @@ -2397,9 +2417,28 @@ class InitializeClassMembersStatement final : public Statement { ZonePtrList<Property>* fields_; }; +class InitializeClassStaticElementsStatement final : public Statement { + public: + using StaticElement = ClassLiteralStaticElement; + + ZonePtrList<StaticElement>* elements() const { return elements_; } + + private: + friend class AstNodeFactory; + friend Zone; + + InitializeClassStaticElementsStatement(ZonePtrList<StaticElement>* elements, + int pos) + : Statement(pos, kInitializeClassStaticElementsStatement), + elements_(elements) {} + + ZonePtrList<StaticElement>* elements_; +}; + class ClassLiteral final : public Expression { public: using Property = ClassLiteralProperty; + using StaticElement = ClassLiteralStaticElement; ClassScope* scope() const { return scope_; } Expression* extends() const { return extends_; } @@ -2425,14 +2464,16 @@ class ClassLiteral final : public Expression { return is_anonymous_expression(); } - FunctionLiteral* static_fields_initializer() const { - return static_fields_initializer_; - } + FunctionLiteral* static_initializer() const { return static_initializer_; } FunctionLiteral* instance_members_initializer_function() const { return instance_members_initializer_function_; } + Variable* home_object() const { return home_object_; } + + Variable* static_home_object() const { return static_home_object_; } + private: friend class AstNodeFactory; friend Zone; @@ -2441,11 +2482,12 @@ class ClassLiteral final : public Expression { FunctionLiteral* constructor, ZonePtrList<Property>* public_members, ZonePtrList<Property>* private_members, - FunctionLiteral* static_fields_initializer, + FunctionLiteral* static_initializer, FunctionLiteral* instance_members_initializer_function, int start_position, int end_position, bool has_name_static_property, bool has_static_computed_names, - bool is_anonymous, bool has_private_methods) + bool is_anonymous, bool has_private_methods, + Variable* home_object, Variable* static_home_object) : Expression(start_position, kClassLiteral), end_position_(end_position), scope_(scope), @@ -2453,9 +2495,11 @@ class ClassLiteral final : public Expression { constructor_(constructor), public_members_(public_members), private_members_(private_members), - static_fields_initializer_(static_fields_initializer), + static_initializer_(static_initializer), instance_members_initializer_function_( - instance_members_initializer_function) { + instance_members_initializer_function), + home_object_(home_object), + static_home_object_(static_home_object) { bit_field_ |= HasNameStaticProperty::encode(has_name_static_property) | HasStaticComputedNames::encode(has_static_computed_names) | IsAnonymousExpression::encode(is_anonymous) | @@ -2468,12 +2512,14 @@ class ClassLiteral final : public Expression { FunctionLiteral* constructor_; ZonePtrList<Property>* public_members_; ZonePtrList<Property>* private_members_; - FunctionLiteral* static_fields_initializer_; + FunctionLiteral* static_initializer_; FunctionLiteral* instance_members_initializer_function_; using HasNameStaticProperty = Expression::NextBitField<bool, 1>; using HasStaticComputedNames = HasNameStaticProperty::Next<bool, 1>; using IsAnonymousExpression = HasStaticComputedNames::Next<bool, 1>; using HasPrivateMethods = IsAnonymousExpression::Next<bool, 1>; + Variable* home_object_; + Variable* static_home_object_; }; @@ -2500,19 +2546,16 @@ class NativeFunctionLiteral final : public Expression { class SuperPropertyReference final : public Expression { public: - Expression* home_object() const { return home_object_; } + VariableProxy* home_object() const { return home_object_; } private: friend class AstNodeFactory; friend Zone; - // We take in ThisExpression* only as a proof that it was accessed. - SuperPropertyReference(Expression* home_object, int pos) - : Expression(pos, kSuperPropertyReference), home_object_(home_object) { - DCHECK(home_object->IsProperty()); - } + explicit SuperPropertyReference(VariableProxy* home_object, int pos) + : Expression(pos, kSuperPropertyReference), home_object_(home_object) {} - Expression* home_object_; + VariableProxy* home_object_; }; @@ -2543,16 +2586,26 @@ class SuperCallReference final : public Expression { // import(argument). class ImportCallExpression final : public Expression { public: - Expression* argument() const { return argument_; } + Expression* specifier() const { return specifier_; } + Expression* import_assertions() const { return import_assertions_; } private: friend class AstNodeFactory; friend Zone; - ImportCallExpression(Expression* argument, int pos) - : Expression(pos, kImportCallExpression), argument_(argument) {} + ImportCallExpression(Expression* specifier, int pos) + : Expression(pos, kImportCallExpression), + specifier_(specifier), + import_assertions_(nullptr) {} + + ImportCallExpression(Expression* specifier, Expression* import_assertions, + int pos) + : Expression(pos, kImportCallExpression), + specifier_(specifier), + import_assertions_(import_assertions) {} - Expression* argument_; + Expression* specifier_; + Expression* import_assertions_; }; // This class is produced when parsing the () in arrow functions without any @@ -2916,11 +2969,6 @@ class AstNodeFactory final { return zone_->New<Literal>(string, pos); } - // A JavaScript symbol (ECMA-262 edition 6). - Literal* NewSymbolLiteral(AstSymbol symbol, int pos) { - return zone_->New<Literal>(symbol, pos); - } - Literal* NewNumberLiteral(double number, int pos); Literal* NewSmiLiteral(int number, int pos) { @@ -2949,9 +2997,10 @@ class AstNodeFactory final { ObjectLiteral* NewObjectLiteral( const ScopedPtrList<ObjectLiteral::Property>& properties, - uint32_t boilerplate_properties, int pos, bool has_rest_property) { + uint32_t boilerplate_properties, int pos, bool has_rest_property, + Variable* home_object = nullptr) { return zone_->New<ObjectLiteral>(zone_, properties, boilerplate_properties, - pos, has_rest_property); + pos, has_rest_property, home_object); } ObjectLiteral::Property* NewObjectLiteralProperty( @@ -3177,20 +3226,32 @@ class AstNodeFactory final { is_computed_name, is_private); } + ClassLiteral::StaticElement* NewClassLiteralStaticElement( + ClassLiteral::Property* property) { + return zone_->New<ClassLiteral::StaticElement>(property); + } + + ClassLiteral::StaticElement* NewClassLiteralStaticElement( + Block* static_block) { + return zone_->New<ClassLiteral::StaticElement>(static_block); + } + ClassLiteral* NewClassLiteral( ClassScope* scope, Expression* extends, FunctionLiteral* constructor, ZonePtrList<ClassLiteral::Property>* public_members, ZonePtrList<ClassLiteral::Property>* private_members, - FunctionLiteral* static_fields_initializer, + FunctionLiteral* static_initializer, FunctionLiteral* instance_members_initializer_function, int start_position, int end_position, bool has_name_static_property, bool has_static_computed_names, bool is_anonymous, - bool has_private_methods) { + bool has_private_methods, Variable* home_object, + Variable* static_home_object) { return zone_->New<ClassLiteral>( scope, extends, constructor, public_members, private_members, - static_fields_initializer, instance_members_initializer_function, + static_initializer, instance_members_initializer_function, start_position, end_position, has_name_static_property, - has_static_computed_names, is_anonymous, has_private_methods); + has_static_computed_names, is_anonymous, has_private_methods, + home_object, static_home_object); } NativeFunctionLiteral* NewNativeFunctionLiteral(const AstRawString* name, @@ -3199,9 +3260,9 @@ class AstNodeFactory final { return zone_->New<NativeFunctionLiteral>(name, extension, pos); } - SuperPropertyReference* NewSuperPropertyReference(Expression* home_object, - int pos) { - return zone_->New<SuperPropertyReference>(home_object, pos); + SuperPropertyReference* NewSuperPropertyReference( + VariableProxy* home_object_var, int pos) { + return zone_->New<SuperPropertyReference>(home_object_var, pos); } SuperCallReference* NewSuperCallReference(VariableProxy* new_target_var, @@ -3227,8 +3288,15 @@ class AstNodeFactory final { return zone_->New<TemplateLiteral>(string_parts, substitutions, pos); } - ImportCallExpression* NewImportCallExpression(Expression* args, int pos) { - return zone_->New<ImportCallExpression>(args, pos); + ImportCallExpression* NewImportCallExpression(Expression* specifier, + int pos) { + return zone_->New<ImportCallExpression>(specifier, pos); + } + + ImportCallExpression* NewImportCallExpression(Expression* specifier, + Expression* import_assertions, + int pos) { + return zone_->New<ImportCallExpression>(specifier, import_assertions, pos); } InitializeClassMembersStatement* NewInitializeClassMembersStatement( @@ -3236,6 +3304,12 @@ class AstNodeFactory final { return zone_->New<InitializeClassMembersStatement>(args, pos); } + InitializeClassStaticElementsStatement* + NewInitializeClassStaticElementsStatement( + ZonePtrList<ClassLiteral::StaticElement>* args, int pos) { + return zone_->New<InitializeClassStaticElementsStatement>(args, pos); + } + Zone* zone() const { return zone_; } private: diff --git a/chromium/v8/src/ast/modules.cc b/chromium/v8/src/ast/modules.cc index 3c9a5080adf..62dc6191414 100644 --- a/chromium/v8/src/ast/modules.cc +++ b/chromium/v8/src/ast/modules.cc @@ -16,44 +16,35 @@ namespace internal { bool SourceTextModuleDescriptor::AstRawStringComparer::operator()( const AstRawString* lhs, const AstRawString* rhs) const { - return ThreeWayCompare(lhs, rhs) < 0; -} - -int SourceTextModuleDescriptor::AstRawStringComparer::ThreeWayCompare( - const AstRawString* lhs, const AstRawString* rhs) { - // Fast path for equal pointers: a pointer is not strictly less than itself. - if (lhs == rhs) return false; - - // Order by contents (ordering by hash is unstable across runs). - if (lhs->is_one_byte() != rhs->is_one_byte()) { - return lhs->is_one_byte() ? -1 : 1; - } - if (lhs->byte_length() != rhs->byte_length()) { - return lhs->byte_length() - rhs->byte_length(); - } - return memcmp(lhs->raw_data(), rhs->raw_data(), lhs->byte_length()); + return AstRawString::Compare(lhs, rhs) < 0; } bool SourceTextModuleDescriptor::ModuleRequestComparer::operator()( const AstModuleRequest* lhs, const AstModuleRequest* rhs) const { - if (int specifier_comparison = AstRawStringComparer::ThreeWayCompare( - lhs->specifier(), rhs->specifier())) + if (int specifier_comparison = + AstRawString::Compare(lhs->specifier(), rhs->specifier())) { return specifier_comparison < 0; - - if (lhs->import_assertions()->size() != rhs->import_assertions()->size()) - return (lhs->import_assertions()->size() < - rhs->import_assertions()->size()); + } auto lhsIt = lhs->import_assertions()->cbegin(); auto rhsIt = rhs->import_assertions()->cbegin(); - for (; lhsIt != lhs->import_assertions()->cend(); ++lhsIt, ++rhsIt) { + for (; lhsIt != lhs->import_assertions()->cend() && + rhsIt != rhs->import_assertions()->cend(); + ++lhsIt, ++rhsIt) { if (int assertion_key_comparison = - AstRawStringComparer::ThreeWayCompare(lhsIt->first, rhsIt->first)) + AstRawString::Compare(lhsIt->first, rhsIt->first)) { return assertion_key_comparison < 0; + } - if (int assertion_value_comparison = AstRawStringComparer::ThreeWayCompare( - lhsIt->second.first, rhsIt->second.first)) + if (int assertion_value_comparison = + AstRawString::Compare(lhsIt->second.first, rhsIt->second.first)) { return assertion_value_comparison < 0; + } + } + + if (lhs->import_assertions()->size() != rhs->import_assertions()->size()) { + return (lhs->import_assertions()->size() < + rhs->import_assertions()->size()); } return false; @@ -139,19 +130,20 @@ Handle<ModuleRequest> SourceTextModuleDescriptor::AstModuleRequest::Serialize( // The import assertions will be stored in this array in the form: // [key1, value1, location1, key2, value2, location2, ...] Handle<FixedArray> import_assertions_array = - isolate->factory()->NewFixedArray( - static_cast<int>(import_assertions()->size() * 3)); + isolate->factory()->NewFixedArray(static_cast<int>( + import_assertions()->size() * ModuleRequest::kAssertionEntrySize)); int i = 0; for (auto iter = import_assertions()->cbegin(); - iter != import_assertions()->cend(); ++iter, i += 3) { + iter != import_assertions()->cend(); + ++iter, i += ModuleRequest::kAssertionEntrySize) { import_assertions_array->set(i, *iter->first->string()); import_assertions_array->set(i + 1, *iter->second.first->string()); import_assertions_array->set(i + 2, Smi::FromInt(iter->second.second.beg_pos)); } return v8::internal::ModuleRequest::New(isolate, specifier()->string(), - import_assertions_array); + import_assertions_array, position()); } template Handle<ModuleRequest> SourceTextModuleDescriptor::AstModuleRequest::Serialize(Isolate* isolate) const; diff --git a/chromium/v8/src/ast/modules.h b/chromium/v8/src/ast/modules.h index f156d7a411a..f776d2b5226 100644 --- a/chromium/v8/src/ast/modules.h +++ b/chromium/v8/src/ast/modules.h @@ -5,6 +5,7 @@ #ifndef V8_AST_MODULES_H_ #define V8_AST_MODULES_H_ +#include "src/parsing/import-assertions.h" #include "src/parsing/scanner.h" // Only for Scanner::Location. #include "src/zone/zone-containers.h" @@ -13,6 +14,7 @@ namespace internal { class AstRawString; +class AstRawStringComparer; class ModuleRequest; class SourceTextModuleInfo; class SourceTextModuleInfoEntry; @@ -27,10 +29,6 @@ class SourceTextModuleDescriptor : public ZoneObject { regular_exports_(zone), regular_imports_(zone) {} - using ImportAssertions = - ZoneMap<const AstRawString*, - std::pair<const AstRawString*, Scanner::Location>>; - // The following Add* methods are high-level convenience functions for use by // the parser. @@ -126,11 +124,13 @@ class SourceTextModuleDescriptor : public ZoneObject { class AstModuleRequest : public ZoneObject { public: - // TODO(v8:10958): Consider storing module request location here - // instead of using separate ModuleRequestLocation struct. AstModuleRequest(const AstRawString* specifier, - const ImportAssertions* import_assertions) - : specifier_(specifier), import_assertions_(import_assertions) {} + const ImportAssertions* import_assertions, int position, + int index) + : specifier_(specifier), + import_assertions_(import_assertions), + position_(position), + index_(index) {} template <typename LocalIsolate> Handle<v8::internal::ModuleRequest> Serialize(LocalIsolate* isolate) const; @@ -140,29 +140,25 @@ class SourceTextModuleDescriptor : public ZoneObject { return import_assertions_; } + int position() const { return position_; } + int index() const { return index_; } + private: const AstRawString* specifier_; const ImportAssertions* import_assertions_; - }; - - struct ModuleRequestLocation { - // The index at which we will place the request in SourceTextModuleInfo's - // module_requests FixedArray. - int index; // The JS source code position of the request, used for reporting errors. - int position; + int position_; - ModuleRequestLocation(int index, int position) - : index(index), position(position) {} + // The index at which we will place the request in SourceTextModuleInfo's + // module_requests FixedArray. + int index_; }; // Custom content-based comparer for the below maps, to keep them stable // across parses. struct V8_EXPORT_PRIVATE AstRawStringComparer { bool operator()(const AstRawString* lhs, const AstRawString* rhs) const; - static int ThreeWayCompare(const AstRawString* lhs, - const AstRawString* rhs); }; struct V8_EXPORT_PRIVATE ModuleRequestComparer { @@ -171,8 +167,7 @@ class SourceTextModuleDescriptor : public ZoneObject { }; using ModuleRequestMap = - ZoneMap<const AstModuleRequest*, ModuleRequestLocation, - ModuleRequestComparer>; + ZoneSet<const AstModuleRequest*, ModuleRequestComparer>; using RegularExportMap = ZoneMultimap<const AstRawString*, Entry*, AstRawStringComparer>; using RegularImportMap = @@ -274,12 +269,11 @@ class SourceTextModuleDescriptor : public ZoneObject { DCHECK_NOT_NULL(specifier); int module_requests_count = static_cast<int>(module_requests_.size()); auto it = module_requests_ - .insert(std::make_pair( - zone->New<AstModuleRequest>(specifier, import_assertions), - ModuleRequestLocation(module_requests_count, - specifier_loc.beg_pos))) + .insert(zone->New<AstModuleRequest>( + specifier, import_assertions, specifier_loc.beg_pos, + module_requests_count)) .first; - return it->second.index; + return (*it)->index(); } }; diff --git a/chromium/v8/src/ast/prettyprinter.cc b/chromium/v8/src/ast/prettyprinter.cc index e53d9c9e6e1..cb8d2ec75af 100644 --- a/chromium/v8/src/ast/prettyprinter.cc +++ b/chromium/v8/src/ast/prettyprinter.cc @@ -235,6 +235,18 @@ void CallPrinter::VisitInitializeClassMembersStatement( } } +void CallPrinter::VisitInitializeClassStaticElementsStatement( + InitializeClassStaticElementsStatement* node) { + for (int i = 0; i < node->elements()->length(); i++) { + ClassLiteral::StaticElement* element = node->elements()->at(i); + if (element->kind() == ClassLiteral::StaticElement::PROPERTY) { + Find(element->property()->value()); + } else { + Find(element->static_block()); + } + } +} + void CallPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {} @@ -256,6 +268,7 @@ void CallPrinter::VisitRegExpLiteral(RegExpLiteral* node) { Print("/"); PrintLiteral(node->pattern(), false); Print("/"); + if (node->flags() & RegExp::kHasIndices) Print("d"); if (node->flags() & RegExp::kGlobal) Print("g"); if (node->flags() & RegExp::kIgnoreCase) Print("i"); if (node->flags() & RegExp::kLinear) Print("l"); @@ -551,7 +564,10 @@ void CallPrinter::VisitTemplateLiteral(TemplateLiteral* node) { void CallPrinter::VisitImportCallExpression(ImportCallExpression* node) { Print("ImportCall("); - Find(node->argument(), true); + Find(node->specifier(), true); + if (node->import_assertions()) { + Find(node->import_assertions(), true); + } Print(")"); } @@ -659,14 +675,6 @@ void AstPrinter::PrintLiteral(Literal* literal, bool quote) { case Literal::kString: PrintLiteral(literal->AsRawString(), quote); break; - case Literal::kSymbol: - const char* symbol; - switch (literal->AsSymbol()) { - case AstSymbol::kHomeObjectSymbol: - symbol = "HomeObjectSymbol"; - } - Print("%s", symbol); - break; case Literal::kSmi: Print("%d", Smi::ToInt(literal->AsSmiLiteral())); break; @@ -721,7 +729,7 @@ void AstPrinter::PrintLiteral(const AstConsString* value, bool quote) { //----------------------------------------------------------------------------- -class IndentedScope { +class V8_NODISCARD IndentedScope { public: IndentedScope(AstPrinter* printer, const char* txt) : ast_printer_(printer) { @@ -745,7 +753,6 @@ class IndentedScope { AstPrinter* ast_printer_; }; - //----------------------------------------------------------------------------- AstPrinter::AstPrinter(uintptr_t stack_limit) @@ -1091,9 +1098,8 @@ void AstPrinter::VisitClassLiteral(ClassLiteral* node) { PrintLiteralWithModeIndented("BRAND", brand, brand->raw_name()); } } - if (node->static_fields_initializer() != nullptr) { - PrintIndentedVisit("STATIC FIELDS INITIALIZER", - node->static_fields_initializer()); + if (node->static_initializer() != nullptr) { + PrintIndentedVisit("STATIC INITIALIZER", node->static_initializer()); } if (node->instance_members_initializer_function() != nullptr) { PrintIndentedVisit("INSTANCE MEMBERS INITIALIZER", @@ -1109,35 +1115,59 @@ void AstPrinter::VisitInitializeClassMembersStatement( PrintClassProperties(node->fields()); } +void AstPrinter::VisitInitializeClassStaticElementsStatement( + InitializeClassStaticElementsStatement* node) { + IndentedScope indent(this, "INITIALIZE CLASS STATIC ELEMENTS", + node->position()); + PrintClassStaticElements(node->elements()); +} + +void AstPrinter::PrintClassProperty(ClassLiteral::Property* property) { + const char* prop_kind = nullptr; + switch (property->kind()) { + case ClassLiteral::Property::METHOD: + prop_kind = "METHOD"; + break; + case ClassLiteral::Property::GETTER: + prop_kind = "GETTER"; + break; + case ClassLiteral::Property::SETTER: + prop_kind = "SETTER"; + break; + case ClassLiteral::Property::FIELD: + prop_kind = "FIELD"; + break; + } + EmbeddedVector<char, 128> buf; + SNPrintF(buf, "PROPERTY%s%s - %s", property->is_static() ? " - STATIC" : "", + property->is_private() ? " - PRIVATE" : " - PUBLIC", prop_kind); + IndentedScope prop(this, buf.begin()); + PrintIndentedVisit("KEY", property->key()); + PrintIndentedVisit("VALUE", property->value()); +} + void AstPrinter::PrintClassProperties( const ZonePtrList<ClassLiteral::Property>* properties) { for (int i = 0; i < properties->length(); i++) { - ClassLiteral::Property* property = properties->at(i); - const char* prop_kind = nullptr; - switch (property->kind()) { - case ClassLiteral::Property::METHOD: - prop_kind = "METHOD"; - break; - case ClassLiteral::Property::GETTER: - prop_kind = "GETTER"; - break; - case ClassLiteral::Property::SETTER: - prop_kind = "SETTER"; + PrintClassProperty(properties->at(i)); + } +} + +void AstPrinter::PrintClassStaticElements( + const ZonePtrList<ClassLiteral::StaticElement>* static_elements) { + for (int i = 0; i < static_elements->length(); i++) { + ClassLiteral::StaticElement* element = static_elements->at(i); + switch (element->kind()) { + case ClassLiteral::StaticElement::PROPERTY: + PrintClassProperty(element->property()); break; - case ClassLiteral::Property::FIELD: - prop_kind = "FIELD"; + case ClassLiteral::StaticElement::STATIC_BLOCK: + PrintIndentedVisit("STATIC BLOCK", element->static_block()); break; } - EmbeddedVector<char, 128> buf; - SNPrintF(buf, "PROPERTY%s%s - %s", property->is_static() ? " - STATIC" : "", - property->is_private() ? " - PRIVATE" : " - PUBLIC", prop_kind); - IndentedScope prop(this, buf.begin()); - PrintIndentedVisit("KEY", properties->at(i)->key()); - PrintIndentedVisit("VALUE", properties->at(i)->value()); } } - void AstPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) { IndentedScope indent(this, "NATIVE FUNC LITERAL", node->position()); PrintLiteralIndented("NAME", node->raw_name(), false); @@ -1162,6 +1192,7 @@ void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) { PrintLiteralIndented("PATTERN", node->raw_pattern(), false); int i = 0; EmbeddedVector<char, 128> buf; + if (node->flags() & RegExp::kHasIndices) buf[i++] = 'd'; if (node->flags() & RegExp::kGlobal) buf[i++] = 'g'; if (node->flags() & RegExp::kIgnoreCase) buf[i++] = 'i'; if (node->flags() & RegExp::kLinear) buf[i++] = 'l'; @@ -1435,7 +1466,10 @@ void AstPrinter::VisitTemplateLiteral(TemplateLiteral* node) { void AstPrinter::VisitImportCallExpression(ImportCallExpression* node) { IndentedScope indent(this, "IMPORT-CALL", node->position()); - Visit(node->argument()); + Visit(node->specifier()); + if (node->import_assertions()) { + Visit(node->import_assertions()); + } } void AstPrinter::VisitThisExpression(ThisExpression* node) { diff --git a/chromium/v8/src/ast/prettyprinter.h b/chromium/v8/src/ast/prettyprinter.h index 4b939c7d17a..e26d98e7a39 100644 --- a/chromium/v8/src/ast/prettyprinter.h +++ b/chromium/v8/src/ast/prettyprinter.h @@ -133,8 +133,11 @@ class AstPrinter final : public AstVisitor<AstPrinter> { const char* prefix = ""); void PrintObjectProperties( const ZonePtrList<ObjectLiteral::Property>* properties); + void PrintClassProperty(ClassLiteral::Property* property); void PrintClassProperties( const ZonePtrList<ClassLiteral::Property>* properties); + void PrintClassStaticElements( + const ZonePtrList<ClassLiteral::StaticElement>* static_elements); void inc_indent() { indent_++; } void dec_indent() { indent_--; } diff --git a/chromium/v8/src/ast/scopes.cc b/chromium/v8/src/ast/scopes.cc index c9a3b400a70..4e396c457f7 100644 --- a/chromium/v8/src/ast/scopes.cc +++ b/chromium/v8/src/ast/scopes.cc @@ -113,6 +113,32 @@ Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type) outer_scope_->AddInnerScope(this); } +Variable* Scope::DeclareHomeObjectVariable(AstValueFactory* ast_value_factory) { + bool was_added; + Variable* home_object_variable = Declare( + zone(), ast_value_factory->dot_home_object_string(), VariableMode::kConst, + NORMAL_VARIABLE, InitializationFlag::kCreatedInitialized, + MaybeAssignedFlag::kNotAssigned, &was_added); + DCHECK(was_added); + home_object_variable->set_is_used(); + home_object_variable->ForceContextAllocation(); + return home_object_variable; +} + +Variable* Scope::DeclareStaticHomeObjectVariable( + AstValueFactory* ast_value_factory) { + bool was_added; + Variable* static_home_object_variable = + Declare(zone(), ast_value_factory->dot_static_home_object_string(), + VariableMode::kConst, NORMAL_VARIABLE, + InitializationFlag::kCreatedInitialized, + MaybeAssignedFlag::kNotAssigned, &was_added); + DCHECK(was_added); + static_home_object_variable->set_is_used(); + static_home_object_variable->ForceContextAllocation(); + return static_home_object_variable; +} + DeclarationScope::DeclarationScope(Zone* zone, AstValueFactory* ast_value_factory, REPLMode repl_mode) @@ -148,7 +174,7 @@ ModuleScope::ModuleScope(DeclarationScope* script_scope, ModuleScope::ModuleScope(Isolate* isolate, Handle<ScopeInfo> scope_info, AstValueFactory* avfactory) - : DeclarationScope(avfactory->zone(), MODULE_SCOPE, scope_info), + : DeclarationScope(avfactory->zone(), MODULE_SCOPE, avfactory, scope_info), module_descriptor_(nullptr) { set_language_mode(LanguageMode::kStrict); } @@ -163,7 +189,7 @@ ClassScope::ClassScope(Zone* zone, Scope* outer_scope, bool is_anonymous) ClassScope::ClassScope(Isolate* isolate, Zone* zone, AstValueFactory* ast_value_factory, Handle<ScopeInfo> scope_info) - : Scope(zone, CLASS_SCOPE, scope_info), + : Scope(zone, CLASS_SCOPE, ast_value_factory, scope_info), rare_data_and_is_parsing_heritage_(nullptr) { set_language_mode(LanguageMode::kStrict); if (scope_info->HasClassBrand()) { @@ -193,7 +219,8 @@ ClassScope::ClassScope(Isolate* isolate, Zone* zone, } } -Scope::Scope(Zone* zone, ScopeType scope_type, Handle<ScopeInfo> scope_info) +Scope::Scope(Zone* zone, ScopeType scope_type, + AstValueFactory* ast_value_factory, Handle<ScopeInfo> scope_info) : outer_scope_(nullptr), variables_(zone), scope_info_(scope_info), @@ -210,11 +237,31 @@ Scope::Scope(Zone* zone, ScopeType scope_type, Handle<ScopeInfo> scope_info) // We don't really need to use the preparsed scope data; this is just to // shorten the recursion in SetMustUsePreparseData. must_use_preparsed_scope_data_ = true; + + if (scope_type == BLOCK_SCOPE) { + // Set is_block_scope_for_object_literal_ based on the existince of the home + // object variable (we don't store it explicitly). + VariableMode mode; + InitializationFlag init_flag; + MaybeAssignedFlag maybe_assigned_flag; + IsStaticFlag is_static_flag; + + DCHECK_NOT_NULL(ast_value_factory); + int home_object_index = ScopeInfo::ContextSlotIndex( + *scope_info, *(ast_value_factory->dot_home_object_string()->string()), + &mode, &init_flag, &maybe_assigned_flag, &is_static_flag); + DCHECK_IMPLIES(home_object_index >= 0, + scope_type == CLASS_SCOPE || scope_type == BLOCK_SCOPE); + if (home_object_index >= 0) { + is_block_scope_for_object_literal_ = true; + } + } } DeclarationScope::DeclarationScope(Zone* zone, ScopeType scope_type, + AstValueFactory* ast_value_factory, Handle<ScopeInfo> scope_info) - : Scope(zone, scope_type, scope_info), + : Scope(zone, scope_type, ast_value_factory, scope_info), function_kind_(scope_info->function_kind()), params_(0, zone) { DCHECK_NE(scope_type, SCRIPT_SCOPE); @@ -252,7 +299,7 @@ void DeclarationScope::SetDefaults() { is_asm_module_ = false; force_eager_compilation_ = false; has_arguments_parameter_ = false; - scope_uses_super_property_ = false; + uses_super_property_ = false; has_checked_syntax_ = false; has_this_reference_ = false; has_this_declaration_ = @@ -308,6 +355,9 @@ void Scope::SetDefaults() { deserialized_scope_uses_external_cache_ = false; + needs_home_object_ = false; + is_block_scope_for_object_literal_ = false; + num_stack_slots_ = 0; num_heap_slots_ = ContextHeaderLength(); @@ -357,13 +407,14 @@ Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone, while (!scope_info.is_null()) { if (scope_info.scope_type() == WITH_SCOPE) { if (scope_info.IsDebugEvaluateScope()) { - outer_scope = zone->New<DeclarationScope>(zone, FUNCTION_SCOPE, - handle(scope_info, isolate)); + outer_scope = + zone->New<DeclarationScope>(zone, FUNCTION_SCOPE, ast_value_factory, + handle(scope_info, isolate)); outer_scope->set_is_debug_evaluate_scope(); } else { // For scope analysis, debug-evaluate is equivalent to a with scope. - outer_scope = - zone->New<Scope>(zone, WITH_SCOPE, handle(scope_info, isolate)); + outer_scope = zone->New<Scope>(zone, WITH_SCOPE, ast_value_factory, + handle(scope_info, isolate)); } } else if (scope_info.scope_type() == SCRIPT_SCOPE) { @@ -377,24 +428,24 @@ Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone, DCHECK(!scope_info.HasOuterScopeInfo()); break; } else if (scope_info.scope_type() == FUNCTION_SCOPE) { - outer_scope = zone->New<DeclarationScope>(zone, FUNCTION_SCOPE, - handle(scope_info, isolate)); + outer_scope = zone->New<DeclarationScope>( + zone, FUNCTION_SCOPE, ast_value_factory, handle(scope_info, isolate)); if (scope_info.IsAsmModule()) { outer_scope->AsDeclarationScope()->set_is_asm_module(); } } else if (scope_info.scope_type() == EVAL_SCOPE) { - outer_scope = zone->New<DeclarationScope>(zone, EVAL_SCOPE, - handle(scope_info, isolate)); + outer_scope = zone->New<DeclarationScope>( + zone, EVAL_SCOPE, ast_value_factory, handle(scope_info, isolate)); } else if (scope_info.scope_type() == CLASS_SCOPE) { outer_scope = zone->New<ClassScope>(isolate, zone, ast_value_factory, handle(scope_info, isolate)); } else if (scope_info.scope_type() == BLOCK_SCOPE) { if (scope_info.is_declaration_scope()) { - outer_scope = zone->New<DeclarationScope>(zone, BLOCK_SCOPE, - handle(scope_info, isolate)); + outer_scope = zone->New<DeclarationScope>( + zone, BLOCK_SCOPE, ast_value_factory, handle(scope_info, isolate)); } else { - outer_scope = - zone->New<Scope>(zone, BLOCK_SCOPE, handle(scope_info, isolate)); + outer_scope = zone->New<Scope>(zone, BLOCK_SCOPE, ast_value_factory, + handle(scope_info, isolate)); } } else if (scope_info.scope_type() == MODULE_SCOPE) { outer_scope = zone->New<ModuleScope>(isolate, handle(scope_info, isolate), @@ -835,7 +886,7 @@ Variable* Scope::LookupInScopeInfo(const AstRawString* name, Scope* cache) { cache != this, cache->outer_scope()->deserialized_scope_uses_external_cache()); DCHECK_NULL(cache->variables_.Lookup(name)); - DisallowHeapAllocation no_gc; + DisallowGarbageCollection no_gc; String name_handle = *name->string(); ScopeInfo scope_info = *scope_info_; @@ -1378,6 +1429,29 @@ DeclarationScope* Scope::GetReceiverScope() { return scope->AsDeclarationScope(); } +Scope* Scope::GetHomeObjectScope() { + Scope* scope = this; + while (scope != nullptr && !scope->is_home_object_scope()) { + if (scope->is_function_scope()) { + FunctionKind function_kind = scope->AsDeclarationScope()->function_kind(); + // "super" in arrow functions binds outside the arrow function. But if we + // find a function which doesn't bind "super" (is not a method etc.) and + // not an arrow function, we know "super" here doesn't bind anywhere and + // we can return nullptr. + if (!IsArrowFunction(function_kind) && !BindsSuper(function_kind)) { + return nullptr; + } + } + if (scope->private_name_lookup_skips_outer_class()) { + DCHECK(scope->outer_scope()->is_class_scope()); + scope = scope->outer_scope()->outer_scope(); + } else { + scope = scope->outer_scope(); + } + } + return scope; +} + DeclarationScope* Scope::GetScriptScope() { Scope* scope = this; while (!scope->is_script_scope()) { @@ -1781,9 +1855,6 @@ void Scope::Print(int n) { AsDeclarationScope()->sloppy_eval_can_extend_vars()) { Indent(n1, "// scope calls sloppy 'eval'\n"); } - if (is_declaration_scope() && AsDeclarationScope()->NeedsHomeObject()) { - Indent(n1, "// scope needs home object\n"); - } if (private_name_lookup_skips_outer_class()) { Indent(n1, "// scope skips outer class for #-names\n"); } @@ -2669,7 +2740,7 @@ void ClassScope::MigrateUnresolvedPrivateNameTail( Variable* ClassScope::LookupPrivateNameInScopeInfo(const AstRawString* name) { DCHECK(!scope_info_.is_null()); DCHECK_NULL(LookupLocalPrivateName(name)); - DisallowHeapAllocation no_gc; + DisallowGarbageCollection no_gc; String name_handle = *name->string(); VariableMode mode; diff --git a/chromium/v8/src/ast/scopes.h b/chromium/v8/src/ast/scopes.h index e731d4c46a0..eb97c95b328 100644 --- a/chromium/v8/src/ast/scopes.h +++ b/chromium/v8/src/ast/scopes.h @@ -225,6 +225,9 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { VariableKind kind = NORMAL_VARIABLE); Variable* DeclareCatchVariableName(const AstRawString* name); + Variable* DeclareHomeObjectVariable(AstValueFactory* ast_value_factory); + Variable* DeclareStaticHomeObjectVariable(AstValueFactory* ast_value_factory); + // Declarations list. base::ThreadedList<Declaration>* declarations() { return &decls_; } @@ -369,6 +372,18 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { bool is_with_scope() const { return scope_type_ == WITH_SCOPE; } bool is_declaration_scope() const { return is_declaration_scope_; } bool is_class_scope() const { return scope_type_ == CLASS_SCOPE; } + bool is_home_object_scope() const { + return is_class_scope() || + (is_block_scope() && is_block_scope_for_object_literal_); + } + bool is_block_scope_for_object_literal() const { + DCHECK_IMPLIES(is_block_scope_for_object_literal_, is_block_scope()); + return is_block_scope_for_object_literal_; + } + void set_is_block_scope_for_object_literal() { + DCHECK(is_block_scope()); + is_block_scope_for_object_literal_ = true; + } bool inner_scope_calls_eval() const { return inner_scope_calls_eval_; } bool private_name_lookup_skips_outer_class() const { @@ -525,6 +540,10 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { // 'this' is bound, and what determines the function kind. DeclarationScope* GetReceiverScope(); + // Find the first class scope or object literal block scope. This is where + // 'super' is bound. + Scope* GetHomeObjectScope(); + DeclarationScope* GetScriptScope(); // Find the innermost outer scope that needs a context. @@ -570,6 +589,16 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { return deserialized_scope_uses_external_cache_; } + bool needs_home_object() const { + DCHECK(is_home_object_scope()); + return needs_home_object_; + } + + void set_needs_home_object() { + DCHECK(is_home_object_scope()); + needs_home_object_ = true; + } + bool RemoveInnerScope(Scope* inner_scope) { DCHECK_NOT_NULL(inner_scope); if (inner_scope == inner_scope_) { @@ -691,7 +720,8 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { MaybeHandle<ScopeInfo> outer_scope); // Construct a scope based on the scope info. - Scope(Zone* zone, ScopeType type, Handle<ScopeInfo> scope_info); + Scope(Zone* zone, ScopeType type, AstValueFactory* ast_value_factory, + Handle<ScopeInfo> scope_info); // Construct a catch scope with a binding for the name. Scope(Zone* zone, const AstRawString* catch_variable_name, @@ -808,6 +838,9 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { // the compilation of the eval will have the "with" scope as the first scope // with this flag enabled. bool deserialized_scope_uses_external_cache_ : 1; + + bool needs_home_object_ : 1; + bool is_block_scope_for_object_literal_ : 1; }; class V8_EXPORT_PRIVATE DeclarationScope : public Scope { @@ -815,6 +848,7 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope { DeclarationScope(Zone* zone, Scope* outer_scope, ScopeType scope_type, FunctionKind function_kind = kNormalFunction); DeclarationScope(Zone* zone, ScopeType scope_type, + AstValueFactory* ast_value_factory, Handle<ScopeInfo> scope_info); // Creates a script scope. DeclarationScope(Zone* zone, AstValueFactory* ast_value_factory, @@ -822,24 +856,21 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope { FunctionKind function_kind() const { return function_kind_; } - bool is_arrow_scope() const { - return is_function_scope() && IsArrowFunction(function_kind_); - } - // Inform the scope that the corresponding code uses "super". void RecordSuperPropertyUsage() { DCHECK(IsConciseMethod(function_kind()) || IsAccessorFunction(function_kind()) || IsClassConstructor(function_kind())); - scope_uses_super_property_ = true; + uses_super_property_ = true; + Scope* home_object_scope = GetHomeObjectScope(); + DCHECK_NOT_NULL(home_object_scope); + home_object_scope->set_needs_home_object(); } - // Does this scope access "super" property (super.foo). - bool NeedsHomeObject() const { - return scope_uses_super_property_ || - (inner_scope_calls_eval_ && (IsConciseMethod(function_kind()) || - IsAccessorFunction(function_kind()) || - IsClassConstructor(function_kind()))); + bool uses_super_property() const { return uses_super_property_; } + + bool is_arrow_scope() const { + return is_function_scope() && IsArrowFunction(function_kind_); } // Inform the scope and outer scopes that the corresponding code contains an @@ -1219,7 +1250,7 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope { // This scope has a parameter called "arguments". bool has_arguments_parameter_ : 1; // This scope uses "super" property ('super.foo'). - bool scope_uses_super_property_ : 1; + bool uses_super_property_ : 1; bool should_eager_compile_ : 1; // Set to true after we have finished lazy parsing the scope. bool was_lazily_parsed_ : 1; @@ -1298,6 +1329,14 @@ void Scope::RecordEvalCall() { calls_eval_ = true; GetDeclarationScope()->RecordDeclarationScopeEvalCall(); RecordInnerScopeEvalCall(); + // The eval contents might access "super" (if it's inside a function that + // binds super). + DeclarationScope* receiver_scope = GetReceiverScope(); + DCHECK(!receiver_scope->is_arrow_scope()); + FunctionKind function_kind = receiver_scope->function_kind(); + if (BindsSuper(function_kind)) { + receiver_scope->RecordSuperPropertyUsage(); + } } Scope::Snapshot::Snapshot(Scope* scope) |