Commit 3113535e authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[interpreter/runtime] Simplify how global declarations are processed

This makes the code a little more specific to what's happening: There is only 1
global scope, and if there is one, we know its declarations are
info->scope()->declarations(). That means we don't need multiple
GlobalDeclarationsBuilders, and we don't need to cache partially serialized
versions of the declarations. One builder is enough, and we can simply walk
those declarations if there are any.

Additionally this CL drops unnecessary information passed into DeclareGlobals:
- Global functions always have the name on the shared function info, so we can
  drop the name.
- Due to lazy feedback vectors there's no point in trying to preinitialize
  global loads. Also this was only preinitializing global loads at the script
  level, not sub functions; without even checking whether the global load was
  used. It may actually have caused us to do more work and allocate more global
  load feedback slots than neccessary.

Change-Id: Ibbdd029abe5a39ba27f7fc9be84670c5d444d98d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1997123
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65725}
parent 69fda08a
This diff is collapsed.
...@@ -50,6 +50,7 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> { ...@@ -50,6 +50,7 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
#undef DECLARE_VISIT #undef DECLARE_VISIT
// Visiting function for declarations list and statements are overridden. // Visiting function for declarations list and statements are overridden.
void VisitGlobalDeclarations(Declaration::List* declarations);
void VisitDeclarations(Declaration::List* declarations); void VisitDeclarations(Declaration::List* declarations);
void VisitStatements(const ZonePtrList<Statement>* statments); void VisitStatements(const ZonePtrList<Statement>* statments);
...@@ -495,7 +496,6 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> { ...@@ -495,7 +496,6 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
GlobalDeclarationsBuilder* globals_builder_; GlobalDeclarationsBuilder* globals_builder_;
BlockCoverageBuilder* block_coverage_builder_; BlockCoverageBuilder* block_coverage_builder_;
ZoneVector<GlobalDeclarationsBuilder*> global_declarations_;
ZoneVector<std::pair<FunctionLiteral*, size_t>> function_literals_; ZoneVector<std::pair<FunctionLiteral*, size_t>> function_literals_;
ZoneVector<std::pair<NativeFunctionLiteral*, size_t>> ZoneVector<std::pair<NativeFunctionLiteral*, size_t>>
native_function_literals_; native_function_literals_;
......
...@@ -48,9 +48,8 @@ Object ThrowRedeclarationError(Isolate* isolate, Handle<String> name, ...@@ -48,9 +48,8 @@ Object ThrowRedeclarationError(Isolate* isolate, Handle<String> name,
Object DeclareGlobal( Object DeclareGlobal(
Isolate* isolate, Handle<JSGlobalObject> global, Handle<String> name, Isolate* isolate, Handle<JSGlobalObject> global, Handle<String> name,
Handle<Object> value, PropertyAttributes attr, bool is_var, Handle<Object> value, PropertyAttributes attr, bool is_var,
bool is_function_declaration, RedeclarationType redeclaration_type, RedeclarationType redeclaration_type,
Handle<FeedbackVector> feedback_vector = Handle<FeedbackVector>(), Handle<FeedbackVector> feedback_vector = Handle<FeedbackVector>()) {
FeedbackSlot slot = FeedbackSlot::Invalid()) {
Handle<ScriptContextTable> script_contexts( Handle<ScriptContextTable> script_contexts(
global->native_context().script_context_table(), isolate); global->native_context().script_context_table(), isolate);
ScriptContextTable::LookupResult lookup; ScriptContextTable::LookupResult lookup;
...@@ -66,7 +65,7 @@ Object DeclareGlobal( ...@@ -66,7 +65,7 @@ Object DeclareGlobal(
// Do the lookup own properties only, see ES5 erratum. // Do the lookup own properties only, see ES5 erratum.
LookupIterator::Configuration lookup_config( LookupIterator::Configuration lookup_config(
LookupIterator::Configuration::OWN_SKIP_INTERCEPTOR); LookupIterator::Configuration::OWN_SKIP_INTERCEPTOR);
if (is_function_declaration) { if (!is_var) {
// For function declarations, use the interceptor on the declaration. For // For function declarations, use the interceptor on the declaration. For
// non-functions, use it only on initialization. // non-functions, use it only on initialization.
lookup_config = LookupIterator::Configuration::OWN; lookup_config = LookupIterator::Configuration::OWN;
...@@ -82,7 +81,6 @@ Object DeclareGlobal( ...@@ -82,7 +81,6 @@ Object DeclareGlobal(
// Skip var re-declarations. // Skip var re-declarations.
if (is_var) return ReadOnlyRoots(isolate).undefined_value(); if (is_var) return ReadOnlyRoots(isolate).undefined_value();
DCHECK(is_function_declaration);
if ((old_attributes & DONT_DELETE) != 0) { if ((old_attributes & DONT_DELETE) != 0) {
// Only allow reconfiguring globals to functions in user code (no // Only allow reconfiguring globals to functions in user code (no
// natives, which are marked as read-only). // natives, which are marked as read-only).
...@@ -111,25 +109,12 @@ Object DeclareGlobal( ...@@ -111,25 +109,12 @@ Object DeclareGlobal(
if (it.state() == LookupIterator::ACCESSOR) it.Delete(); if (it.state() == LookupIterator::ACCESSOR) it.Delete();
} }
if (is_function_declaration) { if (!is_var) it.Restart();
it.Restart();
}
// Define or redefine own property. // Define or redefine own property.
RETURN_FAILURE_ON_EXCEPTION( RETURN_FAILURE_ON_EXCEPTION(
isolate, JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, attr)); isolate, JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, attr));
if (!feedback_vector.is_null() &&
it.state() != LookupIterator::State::INTERCEPTOR) {
DCHECK_EQ(*global, *it.GetHolder<Object>());
// Preinitialize the feedback slot if the global object does not have
// named interceptor or the interceptor is not masking.
if (!global->HasNamedInterceptor() ||
global->GetNamedInterceptor().non_masking()) {
FeedbackNexus nexus(feedback_vector, slot);
nexus.ConfigurePropertyCellMode(it.GetPropertyCell());
}
}
return ReadOnlyRoots(isolate).undefined_value(); return ReadOnlyRoots(isolate).undefined_value();
} }
...@@ -154,32 +139,23 @@ Object DeclareGlobals(Isolate* isolate, Handle<FixedArray> declarations, ...@@ -154,32 +139,23 @@ Object DeclareGlobals(Isolate* isolate, Handle<FixedArray> declarations,
// Traverse the name/value pairs and set the properties. // Traverse the name/value pairs and set the properties.
int length = declarations->length(); int length = declarations->length();
FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < length, i += 4, { FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < length, i++, {
Handle<String> name(String::cast(declarations->get(i)), isolate); Handle<Object> decl(declarations->get(i), isolate);
FeedbackSlot slot(Smi::ToInt(declarations->get(i + 1))); Handle<String> name;
Handle<Object> possibly_feedback_cell_slot(declarations->get(i + 2),
isolate);
Handle<Object> initial_value(declarations->get(i + 3), isolate);
bool is_var = initial_value->IsUndefined(isolate);
bool is_function = initial_value->IsSharedFunctionInfo();
DCHECK_NE(is_var, is_function);
Handle<Object> value; Handle<Object> value;
if (is_function) { bool is_var = decl->IsString();
DCHECK(possibly_feedback_cell_slot->IsSmi());
Handle<FeedbackCell> feedback_cell = if (is_var) {
closure_feedback_cell_array->GetFeedbackCell( name = Handle<String>::cast(decl);
Smi::ToInt(*possibly_feedback_cell_slot));
// Copy the function and update its context. Use it as value.
Handle<SharedFunctionInfo> shared =
Handle<SharedFunctionInfo>::cast(initial_value);
Handle<JSFunction> function =
isolate->factory()->NewFunctionFromSharedFunctionInfo(
shared, context, feedback_cell, AllocationType::kOld);
value = function;
} else {
value = isolate->factory()->undefined_value(); value = isolate->factory()->undefined_value();
} else {
Handle<SharedFunctionInfo> sfi = Handle<SharedFunctionInfo>::cast(decl);
name = handle(sfi->Name(), isolate);
int index = Smi::ToInt(declarations->get(++i));
Handle<FeedbackCell> feedback_cell =
closure_feedback_cell_array->GetFeedbackCell(index);
value = isolate->factory()->NewFunctionFromSharedFunctionInfo(
sfi, context, feedback_cell, AllocationType::kOld);
} }
// Compute the property attributes. According to ECMA-262, // Compute the property attributes. According to ECMA-262,
...@@ -190,10 +166,9 @@ Object DeclareGlobals(Isolate* isolate, Handle<FixedArray> declarations, ...@@ -190,10 +166,9 @@ Object DeclareGlobals(Isolate* isolate, Handle<FixedArray> declarations,
// ES#sec-globaldeclarationinstantiation 5.d: // ES#sec-globaldeclarationinstantiation 5.d:
// If hasRestrictedGlobal is true, throw a SyntaxError exception. // If hasRestrictedGlobal is true, throw a SyntaxError exception.
Object result = DeclareGlobal(isolate, global, name, value, Object result = DeclareGlobal(
static_cast<PropertyAttributes>(attr), is_var, isolate, global, name, value, static_cast<PropertyAttributes>(attr),
is_function, RedeclarationType::kSyntaxError, is_var, RedeclarationType::kSyntaxError, feedback_vector);
feedback_vector, slot);
if (isolate->has_pending_exception()) return result; if (isolate->has_pending_exception()) return result;
}); });
...@@ -228,9 +203,8 @@ Object DeclareEvalHelper(Isolate* isolate, Handle<String> name, ...@@ -228,9 +203,8 @@ Object DeclareEvalHelper(Isolate* isolate, Handle<String> name,
(context->IsBlockContext() && (context->IsBlockContext() &&
context->scope_info().is_declaration_scope())); context->scope_info().is_declaration_scope()));
bool is_function = value->IsJSFunction(); bool is_var = value->IsUndefined(isolate);
bool is_var = !is_function; DCHECK_IMPLIES(!is_var, value->IsJSFunction());
DCHECK(!is_var || value->IsUndefined(isolate));
int index; int index;
PropertyAttributes attributes; PropertyAttributes attributes;
...@@ -249,20 +223,19 @@ Object DeclareEvalHelper(Isolate* isolate, Handle<String> name, ...@@ -249,20 +223,19 @@ Object DeclareEvalHelper(Isolate* isolate, Handle<String> name,
// ES#sec-evaldeclarationinstantiation 8.a.iv.1.b: // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b:
// If fnDefinable is false, throw a TypeError exception. // If fnDefinable is false, throw a TypeError exception.
return DeclareGlobal(isolate, Handle<JSGlobalObject>::cast(holder), name, return DeclareGlobal(isolate, Handle<JSGlobalObject>::cast(holder), name,
value, NONE, is_var, is_function, value, NONE, is_var, RedeclarationType::kTypeError);
RedeclarationType::kTypeError);
} }
if (context->has_extension() && context->extension().IsJSGlobalObject()) { if (context->has_extension() && context->extension().IsJSGlobalObject()) {
Handle<JSGlobalObject> global(JSGlobalObject::cast(context->extension()), Handle<JSGlobalObject> global(JSGlobalObject::cast(context->extension()),
isolate); isolate);
return DeclareGlobal(isolate, global, name, value, NONE, is_var, return DeclareGlobal(isolate, global, name, value, NONE, is_var,
is_function, RedeclarationType::kTypeError); RedeclarationType::kTypeError);
} else if (context->IsScriptContext()) { } else if (context->IsScriptContext()) {
DCHECK(context->global_object().IsJSGlobalObject()); DCHECK(context->global_object().IsJSGlobalObject());
Handle<JSGlobalObject> global( Handle<JSGlobalObject> global(
JSGlobalObject::cast(context->global_object()), isolate); JSGlobalObject::cast(context->global_object()), isolate);
return DeclareGlobal(isolate, global, name, value, NONE, is_var, return DeclareGlobal(isolate, global, name, value, NONE, is_var,
is_function, RedeclarationType::kTypeError); RedeclarationType::kTypeError);
} }
if (attributes != ABSENT) { if (attributes != ABSENT) {
...@@ -271,7 +244,6 @@ Object DeclareEvalHelper(Isolate* isolate, Handle<String> name, ...@@ -271,7 +244,6 @@ Object DeclareEvalHelper(Isolate* isolate, Handle<String> name,
// Skip var re-declarations. // Skip var re-declarations.
if (is_var) return ReadOnlyRoots(isolate).undefined_value(); if (is_var) return ReadOnlyRoots(isolate).undefined_value();
DCHECK(is_function);
if (index != Context::kNotFound) { if (index != Context::kNotFound) {
DCHECK(holder.is_identical_to(context)); DCHECK(holder.is_identical_to(context));
context->set(index, *value); context->set(index, *value);
......
...@@ -22,7 +22,7 @@ bytecodes: [ ...@@ -22,7 +22,7 @@ bytecodes: [
B(Mov), R(closure), R(3), B(Mov), R(closure), R(3),
B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(3), B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(3),
/* 8 S> */ B(LdaSmi), I8(1), /* 8 S> */ B(LdaSmi), I8(1),
/* 8 E> */ B(StaGlobal), U8(1), U8(2), /* 8 E> */ B(StaGlobal), U8(1), U8(0),
B(LdaUndefined), B(LdaUndefined),
/* 11 S> */ B(Return), /* 11 S> */ B(Return),
] ]
...@@ -74,9 +74,9 @@ bytecodes: [ ...@@ -74,9 +74,9 @@ bytecodes: [
B(Mov), R(closure), R(3), B(Mov), R(closure), R(3),
B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(3), B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(3),
/* 8 S> */ B(LdaSmi), I8(1), /* 8 S> */ B(LdaSmi), I8(1),
/* 8 E> */ B(StaGlobal), U8(1), U8(2), /* 8 E> */ B(StaGlobal), U8(1), U8(0),
/* 11 S> */ B(LdaSmi), I8(2), /* 11 S> */ B(LdaSmi), I8(2),
/* 12 E> */ B(StaGlobal), U8(1), U8(2), /* 12 E> */ B(StaGlobal), U8(1), U8(0),
B(Star), R(0), B(Star), R(0),
/* 16 S> */ B(Return), /* 16 S> */ B(Return),
] ]
......
...@@ -21,12 +21,12 @@ bytecodes: [ ...@@ -21,12 +21,12 @@ bytecodes: [
B(Star), R(2), B(Star), R(2),
B(Mov), R(closure), R(3), B(Mov), R(closure), R(3),
B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(3), B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(3),
/* 8 S> */ B(CreateObjectLiteral), U8(1), U8(2), U8(41), /* 8 S> */ B(CreateObjectLiteral), U8(1), U8(0), U8(41),
B(Star), R(1), B(Star), R(1),
/* 16 E> */ B(CreateClosure), U8(2), U8(0), U8(0), /* 16 E> */ B(CreateClosure), U8(2), U8(0), U8(0),
B(StaNamedOwnProperty), R(1), U8(3), U8(3), B(StaNamedOwnProperty), R(1), U8(3), U8(1),
B(Ldar), R(1), B(Ldar), R(1),
/* 8 E> */ B(StaGlobal), U8(4), U8(5), /* 8 E> */ B(StaGlobal), U8(4), U8(3),
B(LdaUndefined), B(LdaUndefined),
/* 34 S> */ B(Return), /* 34 S> */ B(Return),
] ]
......
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