Commit 7ff114e2 authored by littledan's avatar littledan Committed by Commit bot

Add strict mode, sloppy mode and strong mode UseCounters

This patch adds UseCounters for the various language modes. This may
be useful for helping us to prioritize future optimization and
language design decisions.

R=adamk
CC=seththompson
BUG=none

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

Cr-Commit-Position: refs/heads/master@{#31841}
parent 35a60c21
...@@ -5430,6 +5430,9 @@ class V8_EXPORT Isolate { ...@@ -5430,6 +5430,9 @@ class V8_EXPORT Isolate {
kSlotsBufferOverflow = 5, kSlotsBufferOverflow = 5,
kObjectObserve = 6, kObjectObserve = 6,
kForcedGC = 7, kForcedGC = 7,
kSloppyMode = 8,
kStrictMode = 9,
kStrongMode = 10,
kUseCounterFeatureCount // This enum value must be last. kUseCounterFeatureCount // This enum value must be last.
}; };
......
...@@ -346,8 +346,8 @@ FunctionLiteral* Parser::DefaultConstructor(bool call_super, Scope* scope, ...@@ -346,8 +346,8 @@ FunctionLiteral* Parser::DefaultConstructor(bool call_super, Scope* scope,
FunctionKind kind = call_super ? FunctionKind::kDefaultSubclassConstructor FunctionKind kind = call_super ? FunctionKind::kDefaultSubclassConstructor
: FunctionKind::kDefaultBaseConstructor; : FunctionKind::kDefaultBaseConstructor;
Scope* function_scope = NewScope(scope, FUNCTION_SCOPE, kind); Scope* function_scope = NewScope(scope, FUNCTION_SCOPE, kind);
function_scope->SetLanguageMode( SetLanguageMode(function_scope,
static_cast<LanguageMode>(language_mode | STRICT)); static_cast<LanguageMode>(language_mode | STRICT));
// Set start and end position to the same value // Set start and end position to the same value
function_scope->set_start_position(pos); function_scope->set_start_position(pos);
function_scope->set_end_position(pos); function_scope->set_end_position(pos);
...@@ -1048,6 +1048,8 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { ...@@ -1048,6 +1048,8 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
FunctionState function_state(&function_state_, &scope_, scope, FunctionState function_state(&function_state_, &scope_, scope,
kNormalFunction, &function_factory); kNormalFunction, &function_factory);
// Don't count the mode in the use counters--give the program a chance
// to enable script/module-wide strict/strong mode below.
scope_->SetLanguageMode(info->language_mode()); scope_->SetLanguageMode(info->language_mode());
ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
bool ok = true; bool ok = true;
...@@ -1190,7 +1192,7 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info, ...@@ -1190,7 +1192,7 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
if (shared_info->is_arrow()) { if (shared_info->is_arrow()) {
Scope* scope = Scope* scope =
NewScope(scope_, FUNCTION_SCOPE, FunctionKind::kArrowFunction); NewScope(scope_, FUNCTION_SCOPE, FunctionKind::kArrowFunction);
scope->SetLanguageMode(shared_info->language_mode()); SetLanguageMode(scope, shared_info->language_mode());
scope->set_start_position(shared_info->start_position()); scope->set_start_position(shared_info->start_position());
ExpressionClassifier formals_classifier; ExpressionClassifier formals_classifier;
ParserFormalParameters formals(scope); ParserFormalParameters formals(scope);
...@@ -1335,13 +1337,11 @@ void* Parser::ParseStatementList(ZoneList<Statement*>* body, int end_token, ...@@ -1335,13 +1337,11 @@ void* Parser::ParseStatementList(ZoneList<Statement*>* body, int end_token,
// Strong mode implies strict mode. If there are several "use strict" // Strong mode implies strict mode. If there are several "use strict"
// / "use strong" directives, do the strict mode changes only once. // / "use strong" directives, do the strict mode changes only once.
if (is_sloppy(scope_->language_mode())) { if (is_sloppy(scope_->language_mode())) {
scope_->SetLanguageMode( RaiseLanguageMode(STRICT);
static_cast<LanguageMode>(scope_->language_mode() | STRICT));
} }
if (use_strong_found) { if (use_strong_found) {
scope_->SetLanguageMode( RaiseLanguageMode(STRONG);
static_cast<LanguageMode>(scope_->language_mode() | STRONG));
if (IsClassConstructor(function_state_->kind())) { if (IsClassConstructor(function_state_->kind())) {
// "use strong" cannot occur in a class constructor body, to avoid // "use strong" cannot occur in a class constructor body, to avoid
// unintuitive strong class object semantics. // unintuitive strong class object semantics.
...@@ -1377,11 +1377,18 @@ void* Parser::ParseStatementList(ZoneList<Statement*>* body, int end_token, ...@@ -1377,11 +1377,18 @@ void* Parser::ParseStatementList(ZoneList<Statement*>* body, int end_token,
// incremented after parsing is done. // incremented after parsing is done.
++use_counts_[v8::Isolate::kUseAsm]; ++use_counts_[v8::Isolate::kUseAsm];
scope_->SetAsmModule(); scope_->SetAsmModule();
} else {
// Should not change mode, but will increment UseCounter
// if appropriate. Ditto usages below.
RaiseLanguageMode(SLOPPY);
} }
} else { } else {
// End of the directive prologue. // End of the directive prologue.
directive_prologue = false; directive_prologue = false;
RaiseLanguageMode(SLOPPY);
} }
} else {
RaiseLanguageMode(SLOPPY);
} }
body->Add(stat, zone()); body->Add(stat, zone());
...@@ -1458,8 +1465,7 @@ void* Parser::ParseModuleItemList(ZoneList<Statement*>* body, bool* ok) { ...@@ -1458,8 +1465,7 @@ void* Parser::ParseModuleItemList(ZoneList<Statement*>* body, bool* ok) {
// ModuleItem* // ModuleItem*
DCHECK(scope_->is_module_scope()); DCHECK(scope_->is_module_scope());
scope_->SetLanguageMode( RaiseLanguageMode(STRICT);
static_cast<LanguageMode>(scope_->language_mode() | STRICT));
while (peek() != Token::EOS) { while (peek() != Token::EOS) {
Statement* stat = ParseModuleItem(CHECK_OK); Statement* stat = ParseModuleItem(CHECK_OK);
...@@ -4189,7 +4195,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( ...@@ -4189,7 +4195,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
declaration_scope != original_declaration_scope) declaration_scope != original_declaration_scope)
? NewScope(declaration_scope, FUNCTION_SCOPE, kind) ? NewScope(declaration_scope, FUNCTION_SCOPE, kind)
: NewScope(scope_, FUNCTION_SCOPE, kind); : NewScope(scope_, FUNCTION_SCOPE, kind);
scope->SetLanguageMode(language_mode); SetLanguageMode(scope, language_mode);
ZoneList<Statement*>* body = NULL; ZoneList<Statement*>* body = NULL;
int arity = -1; int arity = -1;
int materialized_literal_count = -1; int materialized_literal_count = -1;
...@@ -4421,7 +4427,7 @@ void Parser::SkipLazyFunctionBody(int* materialized_literal_count, ...@@ -4421,7 +4427,7 @@ void Parser::SkipLazyFunctionBody(int* materialized_literal_count,
total_preparse_skipped_ += scope_->end_position() - function_block_pos; total_preparse_skipped_ += scope_->end_position() - function_block_pos;
*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()); SetLanguageMode(scope_, entry.language_mode());
if (entry.uses_super_property()) scope_->RecordSuperPropertyUsage(); if (entry.uses_super_property()) scope_->RecordSuperPropertyUsage();
if (entry.calls_eval()) scope_->RecordEvalCall(); if (entry.calls_eval()) scope_->RecordEvalCall();
return; return;
...@@ -4457,7 +4463,7 @@ void Parser::SkipLazyFunctionBody(int* materialized_literal_count, ...@@ -4457,7 +4463,7 @@ void Parser::SkipLazyFunctionBody(int* materialized_literal_count,
total_preparse_skipped_ += scope_->end_position() - function_block_pos; total_preparse_skipped_ += scope_->end_position() - function_block_pos;
*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()); SetLanguageMode(scope_, logger.language_mode());
if (logger.uses_super_property()) { if (logger.uses_super_property()) {
scope_->RecordSuperPropertyUsage(); scope_->RecordSuperPropertyUsage();
} }
...@@ -4729,7 +4735,7 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody( ...@@ -4729,7 +4735,7 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
if (!parameters.is_simple) { if (!parameters.is_simple) {
DCHECK_NOT_NULL(inner_scope); DCHECK_NOT_NULL(inner_scope);
DCHECK_EQ(body, inner_block->statements()); DCHECK_EQ(body, inner_block->statements());
scope_->SetLanguageMode(inner_scope->language_mode()); SetLanguageMode(scope_, inner_scope->language_mode());
Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK);
DCHECK_NOT_NULL(init_block); DCHECK_NOT_NULL(init_block);
...@@ -4833,8 +4839,7 @@ ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name, ...@@ -4833,8 +4839,7 @@ ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name,
Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
BlockState block_state(&scope_, block_scope); BlockState block_state(&scope_, block_scope);
scope_->SetLanguageMode( RaiseLanguageMode(STRICT);
static_cast<LanguageMode>(scope_->language_mode() | STRICT));
scope_->SetScopeName(name); scope_->SetScopeName(name);
VariableProxy* proxy = NULL; VariableProxy* proxy = NULL;
...@@ -6371,5 +6376,27 @@ Expression* Parser::SpreadCallNew(Expression* function, ...@@ -6371,5 +6376,27 @@ Expression* Parser::SpreadCallNew(Expression* function,
return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, pos); return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, pos);
} }
void Parser::SetLanguageMode(Scope* scope, LanguageMode mode) {
v8::Isolate::UseCounterFeature feature;
if (is_sloppy(mode))
feature = v8::Isolate::kSloppyMode;
else if (is_strong(mode))
feature = v8::Isolate::kStrongMode;
else if (is_strict(mode))
feature = v8::Isolate::kStrictMode;
else
UNREACHABLE();
++use_counts_[feature];
scope->SetLanguageMode(mode);
}
void Parser::RaiseLanguageMode(LanguageMode mode) {
SetLanguageMode(scope_,
static_cast<LanguageMode>(scope_->language_mode() | mode));
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -1199,6 +1199,9 @@ class Parser : public ParserBase<ParserTraits> { ...@@ -1199,6 +1199,9 @@ class Parser : public ParserBase<ParserTraits> {
Expression* SpreadCallNew(Expression* function, Expression* SpreadCallNew(Expression* function,
ZoneList<v8::internal::Expression*>* args, int pos); ZoneList<v8::internal::Expression*>* args, int pos);
void SetLanguageMode(Scope* scope, LanguageMode mode);
void RaiseLanguageMode(LanguageMode mode);
Scanner scanner_; Scanner scanner_;
PreParser* reusable_preparser_; PreParser* reusable_preparser_;
Scope* original_scope_; // for ES5 function declarations in sloppy eval Scope* original_scope_; // for ES5 function declarations in sloppy eval
......
...@@ -3548,6 +3548,47 @@ TEST(UseConstLegacyCount) { ...@@ -3548,6 +3548,47 @@ TEST(UseConstLegacyCount) {
} }
TEST(StrictModeUseCount) {
i::Isolate* isolate = CcTest::i_isolate();
i::HandleScope scope(isolate);
LocalContext env;
int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
global_use_counts = use_counts;
CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
CompileRun(
"\"use strict\";\n"
"function bar() { var baz = 1; }"); // strict mode inherits
CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
CHECK_EQ(0, use_counts[v8::Isolate::kSloppyMode]);
}
TEST(SloppyModeUseCount) {
i::Isolate* isolate = CcTest::i_isolate();
i::HandleScope scope(isolate);
LocalContext env;
int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
global_use_counts = use_counts;
CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
CompileRun("function bar() { var baz = 1; }");
CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]);
CHECK_EQ(0, use_counts[v8::Isolate::kStrictMode]);
}
TEST(BothModesUseCount) {
i::Isolate* isolate = CcTest::i_isolate();
i::HandleScope scope(isolate);
LocalContext env;
int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
global_use_counts = use_counts;
CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
CompileRun("function bar() { 'use strict'; var baz = 1; }");
CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]);
CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
}
TEST(ErrorsArrowFormalParameters) { TEST(ErrorsArrowFormalParameters) {
const char* context_data[][2] = { const char* context_data[][2] = {
{ "()", "=>{}" }, { "()", "=>{}" },
......
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