Commit 765e002a authored by arv's avatar arv Committed by Commit bot

Fix lazy parsing for functions that use super.

The preparser needs to log the usage of super properties and then update
the scope when we create the function later.

BUG=v8:3888
LOG=N
R=dslomov@chromium.org, marja

Review URL: https://codereview.chromium.org/923683002

Cr-Commit-Position: refs/heads/master@{#26642}
parent d273636e
...@@ -3870,6 +3870,7 @@ void Parser::SkipLazyFunctionBody(const AstRawString* function_name, ...@@ -3870,6 +3870,7 @@ void Parser::SkipLazyFunctionBody(const AstRawString* function_name,
*materialized_literal_count = entry.literal_count(); *materialized_literal_count = entry.literal_count();
*expected_property_count = entry.property_count(); *expected_property_count = entry.property_count();
scope_->SetLanguageMode(entry.language_mode()); scope_->SetLanguageMode(entry.language_mode());
if (entry.uses_super_property()) scope_->RecordSuperPropertyUsage();
return; return;
} }
cached_parse_data_->Reject(); cached_parse_data_->Reject();
...@@ -3901,12 +3902,16 @@ void Parser::SkipLazyFunctionBody(const AstRawString* function_name, ...@@ -3901,12 +3902,16 @@ void Parser::SkipLazyFunctionBody(const AstRawString* function_name,
*materialized_literal_count = logger.literals(); *materialized_literal_count = logger.literals();
*expected_property_count = logger.properties(); *expected_property_count = logger.properties();
scope_->SetLanguageMode(logger.language_mode()); scope_->SetLanguageMode(logger.language_mode());
if (logger.scope_uses_super_property()) {
scope_->RecordSuperPropertyUsage();
}
if (produce_cached_parse_data()) { if (produce_cached_parse_data()) {
DCHECK(log_); DCHECK(log_);
// Position right after terminal '}'. // Position right after terminal '}'.
int body_end = scanner()->location().end_pos; int body_end = scanner()->location().end_pos;
log_->LogFunction(function_block_pos, body_end, *materialized_literal_count, log_->LogFunction(function_block_pos, body_end, *materialized_literal_count,
*expected_property_count, scope_->language_mode()); *expected_property_count, scope_->language_mode(),
scope_->uses_super_property());
} }
} }
......
...@@ -32,6 +32,7 @@ class FunctionEntry BASE_EMBEDDED { ...@@ -32,6 +32,7 @@ class FunctionEntry BASE_EMBEDDED {
kLiteralCountIndex, kLiteralCountIndex,
kPropertyCountIndex, kPropertyCountIndex,
kLanguageModeIndex, kLanguageModeIndex,
kUsesSuperPropertyIndex,
kSize kSize
}; };
...@@ -48,6 +49,7 @@ class FunctionEntry BASE_EMBEDDED { ...@@ -48,6 +49,7 @@ class FunctionEntry BASE_EMBEDDED {
DCHECK(is_valid_language_mode(backing_[kLanguageModeIndex])); DCHECK(is_valid_language_mode(backing_[kLanguageModeIndex]));
return static_cast<LanguageMode>(backing_[kLanguageModeIndex]); return static_cast<LanguageMode>(backing_[kLanguageModeIndex]);
} }
bool uses_super_property() { return backing_[kUsesSuperPropertyIndex]; }
bool is_valid() { return !backing_.is_empty(); } bool is_valid() { return !backing_.is_empty(); }
......
...@@ -14,7 +14,7 @@ struct PreparseDataConstants { ...@@ -14,7 +14,7 @@ struct PreparseDataConstants {
public: public:
// Layout and constants of the preparse data exchange format. // Layout and constants of the preparse data exchange format.
static const unsigned kMagicNumber = 0xBadDead; static const unsigned kMagicNumber = 0xBadDead;
static const unsigned kCurrentVersion = 9; static const unsigned kCurrentVersion = 10;
static const int kMagicOffset = 0; static const int kMagicOffset = 0;
static const int kVersionOffset = 1; static const int kVersionOffset = 1;
......
...@@ -24,7 +24,8 @@ class ParserRecorder { ...@@ -24,7 +24,8 @@ class ParserRecorder {
// Logs the scope and some details of a function literal in the source. // Logs the scope and some details of a function literal in the source.
virtual void LogFunction(int start, int end, int literals, int properties, virtual void LogFunction(int start, int end, int literals, int properties,
LanguageMode language_mode) = 0; LanguageMode language_mode,
bool uses_super_property) = 0;
// Logs an error message and marks the log as containing an error. // Logs an error message and marks the log as containing an error.
// Further logging will be ignored, and ExtractData will return a vector // Further logging will be ignored, and ExtractData will return a vector
...@@ -48,13 +49,15 @@ class SingletonLogger : public ParserRecorder { ...@@ -48,13 +49,15 @@ class SingletonLogger : public ParserRecorder {
void Reset() { has_error_ = false; } void Reset() { has_error_ = false; }
virtual void LogFunction(int start, int end, int literals, int properties, virtual void LogFunction(int start, int end, int literals, int properties,
LanguageMode language_mode) { LanguageMode language_mode,
bool scope_uses_super_property) {
DCHECK(!has_error_); DCHECK(!has_error_);
start_ = start; start_ = start;
end_ = end; end_ = end;
literals_ = literals; literals_ = literals;
properties_ = properties; properties_ = properties;
language_mode_ = language_mode; language_mode_ = language_mode;
scope_uses_super_property_ = scope_uses_super_property;
} }
// Logs an error message and marks the log as containing an error. // Logs an error message and marks the log as containing an error.
...@@ -90,6 +93,10 @@ class SingletonLogger : public ParserRecorder { ...@@ -90,6 +93,10 @@ class SingletonLogger : public ParserRecorder {
DCHECK(!has_error_); DCHECK(!has_error_);
return language_mode_; return language_mode_;
} }
bool scope_uses_super_property() const {
DCHECK(!has_error_);
return scope_uses_super_property_;
}
int is_reference_error() const { return is_reference_error_; } int is_reference_error() const { return is_reference_error_; }
const char* message() { const char* message() {
DCHECK(has_error_); DCHECK(has_error_);
...@@ -108,6 +115,7 @@ class SingletonLogger : public ParserRecorder { ...@@ -108,6 +115,7 @@ class SingletonLogger : public ParserRecorder {
int literals_; int literals_;
int properties_; int properties_;
LanguageMode language_mode_; LanguageMode language_mode_;
bool scope_uses_super_property_;
// For error messages. // For error messages.
const char* message_; const char* message_;
const char* argument_opt_; const char* argument_opt_;
...@@ -126,12 +134,14 @@ class CompleteParserRecorder : public ParserRecorder { ...@@ -126,12 +134,14 @@ class CompleteParserRecorder : public ParserRecorder {
virtual ~CompleteParserRecorder() {} virtual ~CompleteParserRecorder() {}
virtual void LogFunction(int start, int end, int literals, int properties, virtual void LogFunction(int start, int end, int literals, int properties,
LanguageMode language_mode) { LanguageMode language_mode,
bool scope_uses_super_property) {
function_store_.Add(start); function_store_.Add(start);
function_store_.Add(end); function_store_.Add(end);
function_store_.Add(literals); function_store_.Add(literals);
function_store_.Add(properties); function_store_.Add(properties);
function_store_.Add(language_mode); function_store_.Add(language_mode);
function_store_.Add(scope_uses_super_property);
} }
// Logs an error message and marks the log as containing an error. // Logs an error message and marks the log as containing an error.
......
...@@ -953,9 +953,10 @@ void PreParser::ParseLazyFunctionLiteralBody(bool* ok) { ...@@ -953,9 +953,10 @@ void PreParser::ParseLazyFunctionLiteralBody(bool* ok) {
// Position right after terminal '}'. // Position right after terminal '}'.
DCHECK_EQ(Token::RBRACE, scanner()->peek()); DCHECK_EQ(Token::RBRACE, scanner()->peek());
int body_end = scanner()->peek_location().end_pos; int body_end = scanner()->peek_location().end_pos;
log_->LogFunction( log_->LogFunction(body_start, body_end,
body_start, body_end, function_state_->materialized_literal_count(), function_state_->materialized_literal_count(),
function_state_->expected_property_count(), language_mode()); function_state_->expected_property_count(), language_mode(),
scope_->uses_super_property());
} }
......
...@@ -371,8 +371,9 @@ Scope* Scope::FinalizeBlockScope() { ...@@ -371,8 +371,9 @@ Scope* Scope::FinalizeBlockScope() {
// Propagate usage flags to outer scope. // Propagate usage flags to outer scope.
if (uses_arguments()) outer_scope_->RecordArgumentsUsage(); if (uses_arguments()) outer_scope_->RecordArgumentsUsage();
if (uses_super_property()) outer_scope_->RecordSuperPropertyUsage(); if (uses_super_property()) outer_scope_->RecordSuperPropertyUsage();
if (uses_super_constructor_call()) if (uses_super_constructor_call()) {
outer_scope_->RecordSuperConstructorCallUsage(); outer_scope_->RecordSuperConstructorCallUsage();
}
if (uses_this()) outer_scope_->RecordThisUsage(); if (uses_this()) outer_scope_->RecordThisUsage();
return NULL; return NULL;
......
...@@ -2527,7 +2527,8 @@ TEST(DontRegressPreParserDataSizes) { ...@@ -2527,7 +2527,8 @@ TEST(DontRegressPreParserDataSizes) {
// No functions. // No functions.
{"var x = 42;", 0}, {"var x = 42;", 0},
// Functions. // Functions.
{"function foo() {}", 1}, {"function foo() {} function bar() {}", 2}, {"function foo() {}", 1},
{"function foo() {} function bar() {}", 2},
// Getter / setter functions are recorded as functions if they're on the top // Getter / setter functions are recorded as functions if they're on the top
// level. // level.
{"var x = {get foo(){} };", 1}, {"var x = {get foo(){} };", 1},
......
...@@ -27,6 +27,7 @@ class Base { ...@@ -27,6 +27,7 @@ class Base {
class Derived extends Base { class Derived extends Base {
constructor() { constructor() {
super();
this._x = 1; this._x = 1;
} }
SuperCall() { SuperCall() {
......
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-classes --min-preparse-length=0
'use strict';
class Base {
m() {
return 42;
}
}
class Derived extends Base {
m() {
return super.m();
}
}
assertEquals(42, new Derived().m());
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment