Commit e093ad73 authored by Marja Hölttä's avatar Marja Hölttä Committed by Commit Bot

[parser] Skipping inner functions: fix recording eval calls.

(The test that catches the bug was test-bytecode-generator/LookupSlot)

BUG=v8:5516

Change-Id: I00a02c5326b2a132383a9d72b5b894fade53bbf2
Reviewed-on: https://chromium-review.googlesource.com/558864
Commit-Queue: Marja Hölttä <marja@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46374}
parent d92628de
...@@ -264,9 +264,16 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { ...@@ -264,9 +264,16 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
// eval call. // eval call.
void RecordEvalCall() { void RecordEvalCall() {
scope_calls_eval_ = true; scope_calls_eval_ = true;
RecordInnerScopeEvalCall();
}
void RecordInnerScopeEvalCall() {
inner_scope_calls_eval_ = true; inner_scope_calls_eval_ = true;
for (Scope* scope = outer_scope(); scope != nullptr; for (Scope* scope = outer_scope(); scope != nullptr;
scope = scope->outer_scope()) { scope = scope->outer_scope()) {
if (scope->inner_scope_calls_eval_) {
return;
}
scope->inner_scope_calls_eval_ = true; scope->inner_scope_calls_eval_ = true;
} }
} }
......
...@@ -16,6 +16,10 @@ namespace internal { ...@@ -16,6 +16,10 @@ namespace internal {
namespace { namespace {
class ScopeCallsEvalField : public BitField<bool, 0, 1> {};
class InnerScopeCallsEvalField
: public BitField<bool, ScopeCallsEvalField::kNext, 1> {};
class VariableIsUsedField : public BitField16<bool, 0, 1> {}; class VariableIsUsedField : public BitField16<bool, 0, 1> {};
class VariableMaybeAssignedField class VariableMaybeAssignedField
: public BitField16<bool, VariableIsUsedField::kNext, 1> {}; : public BitField16<bool, VariableIsUsedField::kNext, 1> {};
...@@ -58,7 +62,7 @@ class UsesSuperField : public BitField<bool, LanguageField::kNext, 1> {}; ...@@ -58,7 +62,7 @@ class UsesSuperField : public BitField<bool, LanguageField::kNext, 1> {};
scope positions scope positions
------------------------------------ ------------------------------------
| scope type << only in debug | | scope type << only in debug |
| inner_scope_calls_eval_ | | eval |
| ---------------------- | | ---------------------- |
| | data for variables | | | | data for variables | |
| | ... | | | | ... | |
...@@ -289,7 +293,11 @@ void ProducedPreParsedScopeData::SaveDataForScope(Scope* scope) { ...@@ -289,7 +293,11 @@ void ProducedPreParsedScopeData::SaveDataForScope(Scope* scope) {
#ifdef DEBUG #ifdef DEBUG
backing_store_.push_back(scope->scope_type()); backing_store_.push_back(scope->scope_type());
#endif #endif
backing_store_.push_back(scope->inner_scope_calls_eval());
uint32_t eval =
ScopeCallsEvalField::encode(scope->calls_eval()) |
InnerScopeCallsEvalField::encode(scope->inner_scope_calls_eval());
backing_store_.push_back(eval);
if (scope->scope_type() == ScopeType::FUNCTION_SCOPE) { if (scope->scope_type() == ScopeType::FUNCTION_SCOPE) {
Variable* function = scope->AsDeclarationScope()->function_var(); Variable* function = scope->AsDeclarationScope()->function_var();
...@@ -369,7 +377,7 @@ ConsumedPreParsedScopeData::GetDataForSkippableFunction( ...@@ -369,7 +377,7 @@ ConsumedPreParsedScopeData::GetDataForSkippableFunction(
// The skippable function *must* be the next function in the data. Use the // The skippable function *must* be the next function in the data. Use the
// start position as a sanity check. // start position as a sanity check.
CHECK_GE(scope_data->length(), index_ + 5); CHECK_GE(scope_data->length(), index_ + SkippableFunctionDataOffsets::kSize);
int start_position_from_data = int start_position_from_data =
scope_data->get(index_ + SkippableFunctionDataOffsets::kStartPosition); scope_data->get(index_ + SkippableFunctionDataOffsets::kStartPosition);
CHECK_EQ(start_position, start_position_from_data); CHECK_EQ(start_position, start_position_from_data);
...@@ -454,9 +462,13 @@ void ConsumedPreParsedScopeData::RestoreData(Scope* scope, ...@@ -454,9 +462,13 @@ void ConsumedPreParsedScopeData::RestoreData(Scope* scope,
DCHECK_GE(scope_data->length(), index_ + 2); DCHECK_GE(scope_data->length(), index_ + 2);
DCHECK_EQ(scope_data->get(index_++), scope->scope_type()); DCHECK_EQ(scope_data->get(index_++), scope->scope_type());
if (scope_data->get(index_++)) { uint32_t eval = scope_data->get(index_++);
if (ScopeCallsEvalField::decode(eval)) {
scope->RecordEvalCall(); scope->RecordEvalCall();
} }
if (InnerScopeCallsEvalField::decode(eval)) {
scope->RecordInnerScopeEvalCall();
}
if (scope->scope_type() == ScopeType::FUNCTION_SCOPE) { if (scope->scope_type() == ScopeType::FUNCTION_SCOPE) {
Variable* function = scope->AsDeclarationScope()->function_var(); Variable* function = scope->AsDeclarationScope()->function_var();
......
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