[super] Store home object in Context instead of JSFunction

This saves memory (the home object doesn't need to be stored for each
method, but only once per class) and hopefully makes the home object
a constant in the optimized code.

Detailed documentation of the changes:
https://docs.google.com/document/d/1ZVXcoQdf9IdMsnRI9iyUjyq9NDoEyx9nA3XqMgwflMs/edit?usp=sharing

Bug: v8:9237
Change-Id: Ia0925bdc8bfe54cbefcba6d10f64746d63a530c7
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2563275
Commit-Queue: Marja Hölttä <marja@chromium.org>
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72137}
This commit is contained in:
Marja Hölttä 2021-01-18 15:47:54 +01:00 committed by Commit Bot
parent a80d51d488
commit 4d5b878b61
47 changed files with 904 additions and 758 deletions

View File

@ -546,7 +546,6 @@ template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitSuperPropertyReference(
SuperPropertyReference* expr) {
PROCESS_EXPRESSION(expr);
RECURSE_EXPRESSION(Visit(expr->home_object()));
}
template <class Subclass>

View File

@ -200,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
@ -229,58 +227,60 @@ 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 {

View File

@ -236,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()) {
@ -581,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:
@ -981,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:
@ -1028,8 +1019,6 @@ bool Literal::ToBooleanIsTrue() const {
}
return false;
}
case kSymbol:
return true;
case kTheHole:
UNREACHABLE();
}

View File

@ -919,7 +919,6 @@ class Literal final : public Expression {
kHeapNumber,
kBigInt,
kString,
kSymbol,
kBoolean,
kUndefined,
kNull,
@ -974,11 +973,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 +1013,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 +1027,6 @@ class Literal final : public Expression {
const AstRawString* string_;
int smi_;
double number_;
AstSymbol symbol_;
AstBigInt bigint_;
bool boolean_;
};
@ -1307,6 +1295,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 +1311,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 +1336,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 +2133,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 +2353,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;
@ -2433,6 +2418,10 @@ class ClassLiteral final : public Expression {
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;
@ -2445,7 +2434,8 @@ class ClassLiteral final : public Expression {
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),
@ -2455,7 +2445,9 @@ class ClassLiteral final : public Expression {
private_members_(private_members),
static_fields_initializer_(static_fields_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) |
@ -2474,6 +2466,8 @@ class ClassLiteral final : public Expression {
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 +2494,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_;
};
@ -2926,11 +2917,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) {
@ -2959,9 +2945,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(
@ -3195,12 +3182,14 @@ class AstNodeFactory final {
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,
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,
@ -3209,9 +3198,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,

View File

@ -662,14 +662,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;

View File

@ -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,6 @@ void DeclarationScope::SetDefaults() {
is_asm_module_ = false;
force_eager_compilation_ = false;
has_arguments_parameter_ = false;
scope_uses_super_property_ = false;
has_checked_syntax_ = false;
has_this_reference_ = false;
has_this_declaration_ =
@ -308,6 +354,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 +406,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 +427,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),
@ -1378,6 +1428,19 @@ DeclarationScope* Scope::GetReceiverScope() {
return scope->AsDeclarationScope();
}
Scope* Scope::GetHomeObjectScope() {
Scope* scope = this;
while (scope != nullptr && !scope->is_home_object_scope()) {
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 +1844,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");
}

View File

@ -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 NeedsHomeObject() const {
return is_home_object_scope() &&
(needs_home_object_ || inner_scope_calls_eval_);
}
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,
@ -826,22 +860,6 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
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;
}
// 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())));
}
// Inform the scope and outer scopes that the corresponding code contains an
// eval call.
void RecordDeclarationScopeEvalCall() {
@ -1218,8 +1236,6 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
bool has_rest_ : 1;
// 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 should_eager_compile_ : 1;
// Set to true after we have finished lazy parsing the scope.
bool was_lazily_parsed_ : 1;

View File

@ -860,8 +860,8 @@ void SharedFunctionInfo::SharedFunctionInfoVerify(ReadOnlyRoots roots) {
CHECK(feedback_metadata().IsFeedbackMetadata());
}
int expected_map_index = Context::FunctionMapIndex(
language_mode(), kind(), HasSharedName(), needs_home_object());
int expected_map_index =
Context::FunctionMapIndex(language_mode(), kind(), HasSharedName());
CHECK_EQ(expected_map_index, function_map_index());
if (!scope_info().IsEmpty()) {

View File

@ -1464,9 +1464,6 @@ void SharedFunctionInfo::SharedFunctionInfoPrint(std::ostream& os) { // NOLINT
}
os << "\n - kind: " << kind();
os << "\n - syntax kind: " << syntax_kind();
if (needs_home_object()) {
os << "\n - needs_home_object";
}
os << "\n - function_map_index: " << function_map_index();
os << "\n - formal_parameter_count: " << internal_formal_parameter_count();
os << "\n - expected_nof_properties: " << expected_nof_properties();

View File

@ -3325,7 +3325,6 @@ Handle<Map> Factory::CreateStrictFunctionMap(
} else {
++descriptors_count; // name accessor.
}
if (IsFunctionModeWithHomeObject(function_mode)) ++inobject_properties_count;
descriptors_count += inobject_properties_count;
Handle<Map> map = NewMap(
@ -3371,15 +3370,6 @@ Handle<Map> Factory::CreateStrictFunctionMap(
map->AppendDescriptor(isolate(), &d);
}
STATIC_ASSERT(JSFunction::kMaybeHomeObjectDescriptorIndex == 2);
if (IsFunctionModeWithHomeObject(function_mode)) {
// Add home object field.
Handle<Name> name = isolate()->factory()->home_object_symbol();
Descriptor d = Descriptor::DataField(isolate(), name, field_index++,
DONT_ENUM, Representation::Tagged());
map->AppendDescriptor(isolate(), &d);
}
if (IsFunctionModeWithPrototype(function_mode)) {
// Add prototype accessor.
PropertyAttributes attribs =

View File

@ -75,25 +75,18 @@ enum class InitializedFlag : uint8_t;
enum FunctionMode {
kWithNameBit = 1 << 0,
kWithHomeObjectBit = 1 << 1,
kWithWritablePrototypeBit = 1 << 2,
kWithReadonlyPrototypeBit = 1 << 3,
kWithWritablePrototypeBit = 1 << 1,
kWithReadonlyPrototypeBit = 1 << 2,
kWithPrototypeBits = kWithWritablePrototypeBit | kWithReadonlyPrototypeBit,
// Without prototype.
FUNCTION_WITHOUT_PROTOTYPE = 0,
METHOD_WITH_NAME = kWithNameBit,
METHOD_WITH_HOME_OBJECT = kWithHomeObjectBit,
METHOD_WITH_NAME_AND_HOME_OBJECT = kWithNameBit | kWithHomeObjectBit,
// With writable prototype.
FUNCTION_WITH_WRITEABLE_PROTOTYPE = kWithWritablePrototypeBit,
FUNCTION_WITH_NAME_AND_WRITEABLE_PROTOTYPE =
kWithWritablePrototypeBit | kWithNameBit,
FUNCTION_WITH_HOME_OBJECT_AND_WRITEABLE_PROTOTYPE =
kWithWritablePrototypeBit | kWithHomeObjectBit,
FUNCTION_WITH_NAME_AND_HOME_OBJECT_AND_WRITEABLE_PROTOTYPE =
kWithWritablePrototypeBit | kWithNameBit | kWithHomeObjectBit,
// With readonly prototype.
FUNCTION_WITH_READONLY_PROTOTYPE = kWithReadonlyPrototypeBit,
@ -705,10 +698,6 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
return (function_mode & kWithNameBit) != 0;
}
static bool IsFunctionModeWithHomeObject(FunctionMode function_mode) {
return (function_mode & kWithHomeObjectBit) != 0;
}
Handle<Map> CreateSloppyFunctionMap(
FunctionMode function_mode, MaybeHandle<JSFunction> maybe_empty_function);

View File

@ -296,10 +296,6 @@ class Genesis {
Handle<NativeContext> native_context_;
Handle<JSGlobalProxy> global_proxy_;
// Temporary function maps needed only during bootstrapping.
Handle<Map> strict_function_with_home_object_map_;
Handle<Map> strict_function_with_name_and_home_object_map_;
// %ThrowTypeError%. See ES#sec-%throwtypeerror% for details.
Handle<JSFunction> restricted_properties_thrower_;
@ -774,13 +770,6 @@ void Genesis::CreateStrictModeFunctionMaps(Handle<JSFunction> empty) {
map = factory->CreateStrictFunctionMap(METHOD_WITH_NAME, empty);
native_context()->set_method_with_name_map(*map);
map = factory->CreateStrictFunctionMap(METHOD_WITH_HOME_OBJECT, empty);
native_context()->set_method_with_home_object_map(*map);
map =
factory->CreateStrictFunctionMap(METHOD_WITH_NAME_AND_HOME_OBJECT, empty);
native_context()->set_method_with_name_and_home_object_map(*map);
//
// Allocate maps for strict functions with writable prototype.
//
@ -792,12 +781,6 @@ void Genesis::CreateStrictModeFunctionMaps(Handle<JSFunction> empty) {
FUNCTION_WITH_NAME_AND_WRITEABLE_PROTOTYPE, empty);
native_context()->set_strict_function_with_name_map(*map);
strict_function_with_home_object_map_ = factory->CreateStrictFunctionMap(
FUNCTION_WITH_HOME_OBJECT_AND_WRITEABLE_PROTOTYPE, empty);
strict_function_with_name_and_home_object_map_ =
factory->CreateStrictFunctionMap(
FUNCTION_WITH_NAME_AND_HOME_OBJECT_AND_WRITEABLE_PROTOTYPE, empty);
//
// Allocate maps for strict functions with readonly prototype.
//
@ -986,17 +969,6 @@ void Genesis::CreateIteratorMaps(Handle<JSFunction> empty) {
generator_function_prototype, "GeneratorFunction with name");
native_context()->set_generator_function_with_name_map(*map);
map = CreateNonConstructorMap(
isolate(), strict_function_with_home_object_map_,
generator_function_prototype, "GeneratorFunction with home object");
native_context()->set_generator_function_with_home_object_map(*map);
map = CreateNonConstructorMap(isolate(),
strict_function_with_name_and_home_object_map_,
generator_function_prototype,
"GeneratorFunction with name and home object");
native_context()->set_generator_function_with_name_and_home_object_map(*map);
Handle<JSFunction> object_function(native_context()->object_function(),
isolate());
Handle<Map> generator_object_prototype_map = Map::Create(isolate(), 0);
@ -1100,19 +1072,6 @@ void Genesis::CreateAsyncIteratorMaps(Handle<JSFunction> empty) {
async_generator_function_prototype, "AsyncGeneratorFunction with name");
native_context()->set_async_generator_function_with_name_map(*map);
map =
CreateNonConstructorMap(isolate(), strict_function_with_home_object_map_,
async_generator_function_prototype,
"AsyncGeneratorFunction with home object");
native_context()->set_async_generator_function_with_home_object_map(*map);
map = CreateNonConstructorMap(
isolate(), strict_function_with_name_and_home_object_map_,
async_generator_function_prototype,
"AsyncGeneratorFunction with name and home object");
native_context()->set_async_generator_function_with_name_and_home_object_map(
*map);
Handle<JSFunction> object_function(native_context()->object_function(),
isolate());
Handle<Map> async_generator_object_prototype_map = Map::Create(isolate(), 0);
@ -1140,16 +1099,6 @@ void Genesis::CreateAsyncFunctionMaps(Handle<JSFunction> empty) {
"AsyncFunction with name");
Map::SetPrototype(isolate(), map, async_function_prototype);
native_context()->set_async_function_with_name_map(*map);
map = Map::Copy(isolate(), isolate()->method_with_home_object_map(),
"AsyncFunction with home object");
Map::SetPrototype(isolate(), map, async_function_prototype);
native_context()->set_async_function_with_home_object_map(*map);
map = Map::Copy(isolate(), isolate()->method_with_name_and_home_object_map(),
"AsyncFunction with name and home object");
Map::SetPrototype(isolate(), map, async_function_prototype);
native_context()->set_async_function_with_name_and_home_object_map(*map);
}
void Genesis::CreateJSProxyMaps() {
@ -1690,9 +1639,6 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
isolate_->strict_function_map()->SetConstructor(*function_fun);
isolate_->strict_function_with_name_map()->SetConstructor(*function_fun);
strict_function_with_home_object_map_->SetConstructor(*function_fun);
strict_function_with_name_and_home_object_map_->SetConstructor(
*function_fun);
isolate_->strict_function_with_readonly_prototype_map()->SetConstructor(
*function_fun);

View File

@ -175,8 +175,10 @@
V(_, dot_default_string, ".default") \
V(_, dot_for_string, ".for") \
V(_, dot_generator_object_string, ".generator_object") \
V(_, dot_home_object_string, ".home_object") \
V(_, dot_result_string, ".result") \
V(_, dot_repl_result_string, ".repl_result") \
V(_, dot_static_home_object_string, "._static_home_object") \
V(_, dot_string, ".") \
V(_, dot_switch_tag_string, ".switch_tag") \
V(_, dotAll_string, "dotAll") \
@ -346,7 +348,6 @@
V(_, error_script_symbol) \
V(_, error_start_pos_symbol) \
V(_, frozen_symbol) \
V(_, home_object_symbol) \
V(_, interpreter_trampoline_symbol) \
V(_, megamorphic_symbol) \
V(_, native_context_index_symbol) \

View File

@ -645,18 +645,6 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(AstBigInt bigint) {
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(AstSymbol symbol) {
size_t entry;
switch (symbol) {
case AstSymbol::kHomeObjectSymbol:
entry = HomeObjectSymbolConstantPoolEntry();
break;
// No default case so that we get a warning if AstSymbol changes
}
OutputLdaConstant(entry);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() {
OutputLdaUndefined();
return *this;
@ -941,12 +929,6 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreInArrayLiteral(
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreHomeObjectProperty(
Register object, int feedback_slot, LanguageMode language_mode) {
size_t name_index = HomeObjectSymbolConstantPoolEntry();
return StoreNamedProperty(object, name_index, feedback_slot, language_mode);
}
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreClassFieldsInitializer(
Register constructor, int feedback_slot) {
size_t name_index = ClassFieldsSymbolConstantPoolEntry();

View File

@ -90,7 +90,6 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final {
BytecodeArrayBuilder& LoadLiteral(const AstRawString* raw_string);
BytecodeArrayBuilder& LoadLiteral(const Scope* scope);
BytecodeArrayBuilder& LoadLiteral(AstBigInt bigint);
BytecodeArrayBuilder& LoadLiteral(AstSymbol symbol);
BytecodeArrayBuilder& LoadUndefined();
BytecodeArrayBuilder& LoadNull();
BytecodeArrayBuilder& LoadTheHole();
@ -200,11 +199,6 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final {
// in the accumulator.
BytecodeArrayBuilder& StoreInArrayLiteral(Register array, Register index,
int feedback_slot);
// Store the home object property. The value to be stored should be in the
// accumulator.
BytecodeArrayBuilder& StoreHomeObjectProperty(Register object,
int feedback_slot,
LanguageMode language_mode);
// Store the class fields property. The initializer to be stored should
// be in the accumulator.

View File

@ -36,7 +36,8 @@ namespace interpreter {
// popping of the current {context_register} during visitation.
class V8_NODISCARD BytecodeGenerator::ContextScope {
public:
ContextScope(BytecodeGenerator* generator, Scope* scope)
ContextScope(BytecodeGenerator* generator, Scope* scope,
Register outer_context_reg = Register())
: generator_(generator),
scope_(scope),
outer_(generator_->execution_context()),
@ -47,8 +48,9 @@ class V8_NODISCARD BytecodeGenerator::ContextScope {
depth_ = outer_->depth_ + 1;
// Push the outer context into a new context register.
Register outer_context_reg =
generator_->register_allocator()->NewRegister();
if (!outer_context_reg.is_valid()) {
outer_context_reg = generator_->register_allocator()->NewRegister();
}
outer_->set_register(outer_context_reg);
generator_->builder()->PushContext(outer_context_reg);
}
@ -64,6 +66,9 @@ class V8_NODISCARD BytecodeGenerator::ContextScope {
generator_->set_execution_context(outer_);
}
ContextScope(const ContextScope&) = delete;
ContextScope& operator=(const ContextScope&) = delete;
// Returns the depth of the given |scope| for the current execution context.
int ContextChainDepth(Scope* scope) {
return scope_->ContextChainLength(scope);
@ -853,12 +858,68 @@ class V8_NODISCARD BytecodeGenerator::CurrentScope final {
generator_->set_current_scope(outer_scope_);
}
}
CurrentScope(const CurrentScope&) = delete;
CurrentScope& operator=(const CurrentScope&) = delete;
private:
BytecodeGenerator* generator_;
Scope* outer_scope_;
};
class V8_NODISCARD BytecodeGenerator::MultipleEntryBlockContextScope {
public:
MultipleEntryBlockContextScope(BytecodeGenerator* generator, Scope* scope)
: generator_(generator), scope_(scope), is_in_scope_(false) {
if (scope) {
inner_context_ = generator->register_allocator()->NewRegister();
outer_context_ = generator->register_allocator()->NewRegister();
generator->BuildNewLocalBlockContext(scope_);
generator->builder()->StoreAccumulatorInRegister(inner_context_);
}
}
void SetEnteredIf(bool condition) {
if (condition && scope_ != nullptr && !is_in_scope_) {
EnterScope();
} else if (!condition && is_in_scope_) {
ExitScope();
}
}
MultipleEntryBlockContextScope(const MultipleEntryBlockContextScope&) =
delete;
MultipleEntryBlockContextScope& operator=(
const MultipleEntryBlockContextScope&) = delete;
private:
void EnterScope() {
DCHECK(inner_context_.is_valid());
DCHECK(outer_context_.is_valid());
DCHECK(!is_in_scope_);
generator_->builder()->LoadAccumulatorWithRegister(inner_context_);
current_scope_.emplace(generator_, scope_);
context_scope_.emplace(generator_, scope_, outer_context_);
is_in_scope_ = true;
}
void ExitScope() {
DCHECK(inner_context_.is_valid());
DCHECK(outer_context_.is_valid());
DCHECK(is_in_scope_);
context_scope_ = base::nullopt;
current_scope_ = base::nullopt;
is_in_scope_ = false;
}
BytecodeGenerator* generator_;
Scope* scope_;
Register inner_context_;
Register outer_context_;
bool is_in_scope_;
base::Optional<CurrentScope> current_scope_;
base::Optional<ContextScope> context_scope_;
};
class BytecodeGenerator::FeedbackSlotCache : public ZoneObject {
public:
enum class SlotKind {
@ -2145,7 +2206,7 @@ void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
}
void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
DCHECK(expr->scope()->outer_scope() == current_scope());
DCHECK_EQ(expr->scope()->outer_scope(), current_scope());
uint8_t flags = CreateClosureFlags::Encode(
expr->pretenure(), closure_scope()->is_function_scope(),
info()->flags().might_always_opt());
@ -2220,9 +2281,10 @@ void BytecodeGenerator::BuildClassLiteral(ClassLiteral* expr, Register name) {
break;
}
case ClassLiteral::Property::METHOD: {
// We can initialize the private methods and accessors later so that the
// home objects can be assigned right after the creation of the
// closures, and those are guarded by the brand checks.
RegisterAllocationScope register_scope(this);
VisitForAccumulatorValue(property->value());
BuildVariableAssignment(property->private_name_var(), Token::INIT,
HoleCheckMode::kElided);
break;
}
// Collect private accessors into a table to merge the creation of
@ -2317,6 +2379,24 @@ void BytecodeGenerator::BuildClassLiteral(ClassLiteral* expr, Register name) {
Register prototype = register_allocator()->NewRegister();
builder()->StoreAccumulatorInRegister(prototype);
// Assign to the home object variable. Accumulator already contains the
// prototype.
Variable* home_object_variable = expr->home_object();
if (home_object_variable != nullptr) {
DCHECK(home_object_variable->is_used());
DCHECK(home_object_variable->IsContextSlot());
BuildVariableAssignment(home_object_variable, Token::INIT,
HoleCheckMode::kElided);
}
Variable* static_home_object_variable = expr->static_home_object();
if (static_home_object_variable != nullptr) {
DCHECK(static_home_object_variable->is_used());
DCHECK(static_home_object_variable->IsContextSlot());
builder()->LoadAccumulatorWithRegister(class_constructor);
BuildVariableAssignment(static_home_object_variable, Token::INIT,
HoleCheckMode::kElided);
}
// Assign to class variable.
Variable* class_variable = expr->scope()->class_variable();
if (class_variable != nullptr && class_variable->is_used()) {
@ -2326,42 +2406,16 @@ void BytecodeGenerator::BuildClassLiteral(ClassLiteral* expr, Register name) {
HoleCheckMode::kElided);
}
// Create the closures of private methods, and store the home object for
// any private methods that need them.
if (expr->has_private_methods()) {
for (int i = 0; i < expr->private_members()->length(); i++) {
ClassLiteral::Property* property = expr->private_members()->at(i);
if (property->kind() != ClassLiteral::Property::METHOD) {
continue;
}
RegisterAllocationScope register_scope(this);
VisitForAccumulatorValue(property->value());
BuildVariableAssignment(property->private_name_var(), Token::INIT,
HoleCheckMode::kElided);
Register home_object = property->private_name_var()->is_static()
? class_constructor
: prototype;
if (property->NeedsHomeObjectOnClassPrototype()) {
Register func = register_allocator()->NewRegister();
builder()->StoreAccumulatorInRegister(func);
VisitSetHomeObject(func, home_object, property);
}
}
}
// Define private accessors, using only a single call to the runtime for
// each pair of corresponding getters and setters, in the order the first
// component is declared. Store the home objects if necessary.
// component is declared.
for (auto accessors : private_accessors.ordered_accessors()) {
RegisterAllocationScope inner_register_scope(this);
RegisterList accessors_reg = register_allocator()->NewRegisterList(2);
ClassLiteral::Property* getter = accessors.second->getter;
ClassLiteral::Property* setter = accessors.second->setter;
bool is_static =
getter != nullptr ? getter->is_static() : setter->is_static();
Register home_object = is_static ? class_constructor : prototype;
VisitLiteralAccessor(home_object, getter, accessors_reg[0]);
VisitLiteralAccessor(home_object, setter, accessors_reg[1]);
VisitLiteralAccessor(getter, accessors_reg[0]);
VisitLiteralAccessor(setter, accessors_reg[1]);
builder()->CallRuntime(Runtime::kCreatePrivateAccessors, accessors_reg);
Variable* var = getter != nullptr ? getter->private_name_var()
: setter->private_name_var();
@ -2373,13 +2427,6 @@ void BytecodeGenerator::BuildClassLiteral(ClassLiteral* expr, Register name) {
Register initializer =
VisitForRegisterValue(expr->instance_members_initializer_function());
if (FunctionLiteral::NeedsHomeObject(
expr->instance_members_initializer_function())) {
FeedbackSlot slot = feedback_spec()->AddStoreICSlot(language_mode());
builder()->LoadAccumulatorWithRegister(prototype).StoreHomeObjectProperty(
initializer, feedback_index(slot), language_mode());
}
FeedbackSlot slot = feedback_spec()->AddStoreICSlot(language_mode());
builder()
->LoadAccumulatorWithRegister(initializer)
@ -2410,14 +2457,6 @@ void BytecodeGenerator::BuildClassLiteral(ClassLiteral* expr, Register name) {
Register initializer =
VisitForRegisterValue(expr->static_fields_initializer());
if (FunctionLiteral::NeedsHomeObject(expr->static_fields_initializer())) {
FeedbackSlot slot = feedback_spec()->AddStoreICSlot(language_mode());
builder()
->LoadAccumulatorWithRegister(class_constructor)
.StoreHomeObjectProperty(initializer, feedback_index(slot),
language_mode());
}
builder()
->MoveRegister(class_constructor, args[0])
.CallProperty(initializer, args,
@ -2475,7 +2514,6 @@ void BytecodeGenerator::VisitInitializeClassMembersStatement(
builder()->SetExpressionAsStatementPosition(property->value());
VisitForRegisterValue(property->value(), value);
VisitSetHomeObject(value, constructor, property);
Runtime::FunctionId function_id =
property->kind() == ClassLiteral::Property::FIELD &&
@ -2595,9 +2633,6 @@ void BytecodeGenerator::VisitLiteral(Literal* expr) {
builder()->LoadLiteral(expr->AsRawString());
execution_result()->SetResultIsString();
break;
case Literal::kSymbol:
builder()->LoadLiteral(expr->AsSymbol());
break;
case Literal::kBigInt:
builder()->LoadLiteral(expr->AsBigInt());
break;
@ -2645,6 +2680,14 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
return;
}
Variable* home_object = expr->home_object();
if (home_object != nullptr) {
DCHECK(home_object->is_used());
DCHECK(home_object->IsContextSlot());
}
MultipleEntryBlockContextScope object_literal_context_scope(
this, home_object ? home_object->scope() : nullptr);
// Deep-copy the literal boilerplate.
uint8_t flags = CreateObjectLiteralFlags::Encode(
expr->ComputeFlags(), expr->IsFastCloningSupported());
@ -2701,21 +2744,14 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
// contains computed properties with an uninitialized value.
if (key->IsStringLiteral()) {
DCHECK(key->IsPropertyName());
object_literal_context_scope.SetEnteredIf(
property->value()->IsConciseMethodDefinition());
if (property->emit_store()) {
builder()->SetExpressionPosition(property->value());
VisitForAccumulatorValue(property->value());
FeedbackSlot slot = feedback_spec()->AddStoreOwnICSlot();
if (FunctionLiteral::NeedsHomeObject(property->value())) {
RegisterAllocationScope register_scope(this);
Register value = register_allocator()->NewRegister();
builder()->StoreAccumulatorInRegister(value);
builder()->StoreNamedOwnProperty(
literal, key->AsRawPropertyName(), feedback_index(slot));
VisitSetHomeObject(value, literal, property);
} else {
builder()->StoreNamedOwnProperty(
literal, key->AsRawPropertyName(), feedback_index(slot));
}
builder()->StoreNamedOwnProperty(literal, key->AsRawPropertyName(),
feedback_index(slot));
} else {
builder()->SetExpressionPosition(property->value());
VisitForEffect(property->value());
@ -2726,12 +2762,13 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
builder()->MoveRegister(literal, args[0]);
builder()->SetExpressionPosition(property->key());
VisitForRegisterValue(property->key(), args[1]);
object_literal_context_scope.SetEnteredIf(
property->value()->IsConciseMethodDefinition());
builder()->SetExpressionPosition(property->value());
VisitForRegisterValue(property->value(), args[2]);
if (property->emit_store()) {
builder()->CallRuntime(Runtime::kSetKeyedProperty, args);
Register value = args[2];
VisitSetHomeObject(value, literal, property);
}
}
break;
@ -2743,6 +2780,7 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
DCHECK(!property->NeedsSetFunctionName());
RegisterList args = register_allocator()->NewRegisterList(2);
builder()->MoveRegister(literal, args[0]);
object_literal_context_scope.SetEnteredIf(false);
builder()->SetExpressionPosition(property->value());
VisitForRegisterValue(property->value(), args[1]);
builder()->CallRuntime(Runtime::kInternalSetPrototype, args);
@ -2763,13 +2801,14 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
// Define accessors, using only a single call to the runtime for each pair of
// corresponding getters and setters.
object_literal_context_scope.SetEnteredIf(true);
for (auto accessors : accessor_table.ordered_accessors()) {
RegisterAllocationScope inner_register_scope(this);
RegisterList args = register_allocator()->NewRegisterList(5);
builder()->MoveRegister(literal, args[0]);
VisitForRegisterValue(accessors.first, args[1]);
VisitLiteralAccessor(literal, accessors.second->getter, args[2]);
VisitLiteralAccessor(literal, accessors.second->setter, args[3]);
VisitLiteralAccessor(accessors.second->getter, args[2]);
VisitLiteralAccessor(accessors.second->setter, args[3]);
builder()
->LoadLiteral(Smi::FromInt(NONE))
.StoreAccumulatorInRegister(args[4])
@ -2789,6 +2828,10 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
ObjectLiteral::Property* property = expr->properties()->at(property_index);
RegisterAllocationScope inner_register_scope(this);
bool should_be_in_object_literal_scope =
(property->value()->IsConciseMethodDefinition() ||
property->value()->IsAccessorFunctionDefinition());
if (property->IsPrototype()) {
// __proto__:null is handled by CreateObjectLiteral.
if (property->IsNullPrototype()) continue;
@ -2796,6 +2839,9 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
DCHECK(!property->NeedsSetFunctionName());
RegisterList args = register_allocator()->NewRegisterList(2);
builder()->MoveRegister(literal, args[0]);
DCHECK(!should_be_in_object_literal_scope);
object_literal_context_scope.SetEnteredIf(false);
builder()->SetExpressionPosition(property->value());
VisitForRegisterValue(property->value(), args[1]);
builder()->CallRuntime(Runtime::kInternalSetPrototype, args);
@ -2808,6 +2854,9 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::MATERIALIZED_LITERAL: {
Register key = register_allocator()->NewRegister();
BuildLoadPropertyKey(property, key);
object_literal_context_scope.SetEnteredIf(
should_be_in_object_literal_scope);
builder()->SetExpressionPosition(property->value());
Register value;
@ -2823,7 +2872,6 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} else {
value = VisitForRegisterValue(property->value());
}
VisitSetHomeObject(value, literal, property);
DataPropertyInLiteralFlags data_property_flags =
DataPropertyInLiteralFlag::kNoFlags;
@ -2844,9 +2892,10 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
RegisterList args = register_allocator()->NewRegisterList(4);
builder()->MoveRegister(literal, args[0]);
BuildLoadPropertyKey(property, args[1]);
DCHECK(should_be_in_object_literal_scope);
object_literal_context_scope.SetEnteredIf(true);
builder()->SetExpressionPosition(property->value());
VisitForRegisterValue(property->value(), args[2]);
VisitSetHomeObject(args[2], literal, property);
builder()
->LoadLiteral(Smi::FromInt(NONE))
.StoreAccumulatorInRegister(args[3]);
@ -2872,6 +2921,10 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
}
builder()->LoadAccumulatorWithRegister(literal);
if (home_object != nullptr) {
object_literal_context_scope.SetEnteredIf(true);
BuildVariableAssignment(home_object, Token::INIT, HoleCheckMode::kElided);
}
}
// Fill an array with values from an iterator, starting at a given index. It is
@ -3520,12 +3573,12 @@ BytecodeGenerator::AssignmentLhsData BytecodeGenerator::PrepareAssignmentLhs(
AccumulatorPreservingScope scope(this, accumulator_preserving_mode);
RegisterList super_property_args =
register_allocator()->NewRegisterList(4);
SuperPropertyReference* super_property =
property->obj()->AsSuperPropertyReference();
BuildThisVariableLoad();
builder()->StoreAccumulatorInRegister(super_property_args[0]);
VisitForRegisterValue(super_property->home_object(),
super_property_args[1]);
BuildVariableLoad(
property->obj()->AsSuperPropertyReference()->home_object()->var(),
HoleCheckMode::kElided);
builder()->StoreAccumulatorInRegister(super_property_args[1]);
builder()
->LoadLiteral(property->key()->AsLiteral()->AsRawPropertyName())
.StoreAccumulatorInRegister(super_property_args[2]);
@ -3535,12 +3588,12 @@ BytecodeGenerator::AssignmentLhsData BytecodeGenerator::PrepareAssignmentLhs(
AccumulatorPreservingScope scope(this, accumulator_preserving_mode);
RegisterList super_property_args =
register_allocator()->NewRegisterList(4);
SuperPropertyReference* super_property =
property->obj()->AsSuperPropertyReference();
BuildThisVariableLoad();
builder()->StoreAccumulatorInRegister(super_property_args[0]);
VisitForRegisterValue(super_property->home_object(),
super_property_args[1]);
BuildVariableLoad(
property->obj()->AsSuperPropertyReference()->home_object()->var(),
HoleCheckMode::kElided);
builder()->StoreAccumulatorInRegister(super_property_args[1]);
VisitForRegisterValue(property->key(), super_property_args[2]);
return AssignmentLhsData::KeyedSuperProperty(super_property_args);
}
@ -4743,13 +4796,13 @@ void BytecodeGenerator::VisitPropertyLoadForRegister(Register obj,
void BytecodeGenerator::VisitNamedSuperPropertyLoad(Property* property,
Register opt_receiver_out) {
RegisterAllocationScope register_scope(this);
SuperPropertyReference* super_property =
property->obj()->AsSuperPropertyReference();
if (FLAG_super_ic) {
Register receiver = register_allocator()->NewRegister();
BuildThisVariableLoad();
builder()->StoreAccumulatorInRegister(receiver);
VisitForAccumulatorValue(super_property->home_object());
BuildVariableLoad(
property->obj()->AsSuperPropertyReference()->home_object()->var(),
HoleCheckMode::kElided);
builder()->SetExpressionPosition(property);
auto name = property->key()->AsLiteral()->AsRawPropertyName();
FeedbackSlot slot = GetCachedLoadSuperICSlot(name);
@ -4761,8 +4814,10 @@ void BytecodeGenerator::VisitNamedSuperPropertyLoad(Property* property,
RegisterList args = register_allocator()->NewRegisterList(3);
BuildThisVariableLoad();
builder()->StoreAccumulatorInRegister(args[0]);
VisitForRegisterValue(super_property->home_object(), args[1]);
BuildVariableLoad(
property->obj()->AsSuperPropertyReference()->home_object()->var(),
HoleCheckMode::kElided);
builder()->StoreAccumulatorInRegister(args[1]);
builder()->SetExpressionPosition(property);
builder()
->LoadLiteral(property->key()->AsLiteral()->AsRawPropertyName())
@ -4778,12 +4833,13 @@ void BytecodeGenerator::VisitNamedSuperPropertyLoad(Property* property,
void BytecodeGenerator::VisitKeyedSuperPropertyLoad(Property* property,
Register opt_receiver_out) {
RegisterAllocationScope register_scope(this);
SuperPropertyReference* super_property =
property->obj()->AsSuperPropertyReference();
RegisterList args = register_allocator()->NewRegisterList(3);
BuildThisVariableLoad();
builder()->StoreAccumulatorInRegister(args[0]);
VisitForRegisterValue(super_property->home_object(), args[1]);
BuildVariableLoad(
property->obj()->AsSuperPropertyReference()->home_object()->var(),
HoleCheckMode::kElided);
builder()->StoreAccumulatorInRegister(args[1]);
VisitForRegisterValue(property->key(), args[2]);
builder()->SetExpressionPosition(property);
@ -5327,11 +5383,12 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
case NAMED_SUPER_PROPERTY: {
super_property_args = register_allocator()->NewRegisterList(4);
RegisterList load_super_args = super_property_args.Truncate(3);
SuperPropertyReference* super_property =
property->obj()->AsSuperPropertyReference();
BuildThisVariableLoad();
builder()->StoreAccumulatorInRegister(load_super_args[0]);
VisitForRegisterValue(super_property->home_object(), load_super_args[1]);
BuildVariableLoad(
property->obj()->AsSuperPropertyReference()->home_object()->var(),
HoleCheckMode::kElided);
builder()->StoreAccumulatorInRegister(load_super_args[1]);
builder()
->LoadLiteral(property->key()->AsLiteral()->AsRawPropertyName())
.StoreAccumulatorInRegister(load_super_args[2])
@ -5341,11 +5398,12 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
case KEYED_SUPER_PROPERTY: {
super_property_args = register_allocator()->NewRegisterList(4);
RegisterList load_super_args = super_property_args.Truncate(3);
SuperPropertyReference* super_property =
property->obj()->AsSuperPropertyReference();
BuildThisVariableLoad();
builder()->StoreAccumulatorInRegister(load_super_args[0]);
VisitForRegisterValue(super_property->home_object(), load_super_args[1]);
BuildVariableLoad(
property->obj()->AsSuperPropertyReference()->home_object()->var(),
HoleCheckMode::kElided);
builder()->StoreAccumulatorInRegister(load_super_args[1]);
VisitForRegisterValue(property->key(), load_super_args[2]);
builder()->CallRuntime(Runtime::kLoadKeyedFromSuper, load_super_args);
break;
@ -6258,25 +6316,12 @@ void BytecodeGenerator::BuildNewLocalCatchContext(Scope* scope) {
builder()->CreateCatchContext(exception, scope);
}
void BytecodeGenerator::VisitLiteralAccessor(Register home_object,
LiteralProperty* property,
void BytecodeGenerator::VisitLiteralAccessor(LiteralProperty* property,
Register value_out) {
if (property == nullptr) {
builder()->LoadNull().StoreAccumulatorInRegister(value_out);
} else {
VisitForRegisterValue(property->value(), value_out);
VisitSetHomeObject(value_out, home_object, property);
}
}
void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object,
LiteralProperty* property) {
Expression* expr = property->value();
if (FunctionLiteral::NeedsHomeObject(expr)) {
FeedbackSlot slot = feedback_spec()->AddStoreICSlot(language_mode());
builder()
->LoadAccumulatorWithRegister(home_object)
.StoreHomeObjectProperty(value, feedback_index(slot), language_mode());
}
}

View File

@ -71,6 +71,7 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
class ExpressionResultScope;
class FeedbackSlotCache;
class IteratorRecord;
class MultipleEntryBlockContextScope;
class LoopScope;
class NaryCodeCoverageSlots;
class OptionalChainNullLabelScope;
@ -325,10 +326,7 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
Register instance);
void BuildGeneratorObjectVariableInitialization();
void VisitBlockDeclarationsAndStatements(Block* stmt);
void VisitSetHomeObject(Register value, Register home_object,
LiteralProperty* property);
void VisitLiteralAccessor(Register home_object, LiteralProperty* property,
Register value_out);
void VisitLiteralAccessor(LiteralProperty* property, Register value_out);
void VisitForInAssignment(Expression* expr);
void VisitModuleNamespaceImports();

View File

@ -29,7 +29,6 @@ namespace interpreter {
V(EmptyObjectBoilerplateDescription, empty_object_boilerplate_description) \
V(EmptyArrayBoilerplateDescription, empty_array_boilerplate_description) \
V(EmptyFixedArray, empty_fixed_array) \
V(HomeObjectSymbol, home_object_symbol) \
V(IteratorSymbol, iterator_symbol) \
V(InterpreterTrampolineSymbol, interpreter_trampoline_symbol) \
V(NaN, nan_value)

View File

@ -182,7 +182,7 @@ NATIVE_CONTEXT_FIELDS(NATIVE_CONTEXT_FIELD_ACCESSORS)
CHECK_FOLLOWS2(v3, v4)
int Context::FunctionMapIndex(LanguageMode language_mode, FunctionKind kind,
bool has_shared_name, bool needs_home_object) {
bool has_shared_name) {
if (IsClassConstructor(kind)) {
// Like the strict function map, but with no 'name' accessor. 'name'
// needs to be the last property and it is added during instantiation,
@ -192,37 +192,27 @@ int Context::FunctionMapIndex(LanguageMode language_mode, FunctionKind kind,
int base = 0;
if (IsGeneratorFunction(kind)) {
CHECK_FOLLOWS4(GENERATOR_FUNCTION_MAP_INDEX,
GENERATOR_FUNCTION_WITH_NAME_MAP_INDEX,
GENERATOR_FUNCTION_WITH_HOME_OBJECT_MAP_INDEX,
GENERATOR_FUNCTION_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX);
CHECK_FOLLOWS4(
ASYNC_GENERATOR_FUNCTION_MAP_INDEX,
ASYNC_GENERATOR_FUNCTION_WITH_NAME_MAP_INDEX,
ASYNC_GENERATOR_FUNCTION_WITH_HOME_OBJECT_MAP_INDEX,
ASYNC_GENERATOR_FUNCTION_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX);
CHECK_FOLLOWS2(GENERATOR_FUNCTION_MAP_INDEX,
GENERATOR_FUNCTION_WITH_NAME_MAP_INDEX);
CHECK_FOLLOWS2(ASYNC_GENERATOR_FUNCTION_MAP_INDEX,
ASYNC_GENERATOR_FUNCTION_WITH_NAME_MAP_INDEX);
base = IsAsyncFunction(kind) ? ASYNC_GENERATOR_FUNCTION_MAP_INDEX
: GENERATOR_FUNCTION_MAP_INDEX;
} else if (IsAsyncFunction(kind) || IsAsyncModule(kind)) {
CHECK_FOLLOWS4(ASYNC_FUNCTION_MAP_INDEX, ASYNC_FUNCTION_WITH_NAME_MAP_INDEX,
ASYNC_FUNCTION_WITH_HOME_OBJECT_MAP_INDEX,
ASYNC_FUNCTION_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX);
CHECK_FOLLOWS2(ASYNC_FUNCTION_MAP_INDEX,
ASYNC_FUNCTION_WITH_NAME_MAP_INDEX);
base = ASYNC_FUNCTION_MAP_INDEX;
} else if (IsStrictFunctionWithoutPrototype(kind)) {
DCHECK_IMPLIES(IsArrowFunction(kind), !needs_home_object);
CHECK_FOLLOWS4(STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
METHOD_WITH_NAME_MAP_INDEX,
METHOD_WITH_HOME_OBJECT_MAP_INDEX,
METHOD_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX);
CHECK_FOLLOWS2(STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
METHOD_WITH_NAME_MAP_INDEX);
base = STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX;
} else {
DCHECK(!needs_home_object);
CHECK_FOLLOWS2(SLOPPY_FUNCTION_MAP_INDEX,
SLOPPY_FUNCTION_WITH_NAME_MAP_INDEX);
CHECK_FOLLOWS2(STRICT_FUNCTION_MAP_INDEX,
@ -231,9 +221,8 @@ int Context::FunctionMapIndex(LanguageMode language_mode, FunctionKind kind,
base = is_strict(language_mode) ? STRICT_FUNCTION_MAP_INDEX
: SLOPPY_FUNCTION_MAP_INDEX;
}
int offset = static_cast<int>(!has_shared_name) |
(static_cast<int>(needs_home_object) << 1);
DCHECK_EQ(0, offset & ~3);
int offset = static_cast<int>(!has_shared_name);
DCHECK_EQ(0, offset & ~1);
return base + offset;
}

View File

@ -253,29 +253,14 @@ enum ContextLookupFlags {
V(STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, \
strict_function_without_prototype_map) \
V(METHOD_WITH_NAME_MAP_INDEX, Map, method_with_name_map) \
V(METHOD_WITH_HOME_OBJECT_MAP_INDEX, Map, method_with_home_object_map) \
V(METHOD_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX, Map, \
method_with_name_and_home_object_map) \
V(ASYNC_FUNCTION_MAP_INDEX, Map, async_function_map) \
V(ASYNC_FUNCTION_WITH_NAME_MAP_INDEX, Map, async_function_with_name_map) \
V(ASYNC_FUNCTION_WITH_HOME_OBJECT_MAP_INDEX, Map, \
async_function_with_home_object_map) \
V(ASYNC_FUNCTION_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX, Map, \
async_function_with_name_and_home_object_map) \
V(GENERATOR_FUNCTION_MAP_INDEX, Map, generator_function_map) \
V(GENERATOR_FUNCTION_WITH_NAME_MAP_INDEX, Map, \
generator_function_with_name_map) \
V(GENERATOR_FUNCTION_WITH_HOME_OBJECT_MAP_INDEX, Map, \
generator_function_with_home_object_map) \
V(GENERATOR_FUNCTION_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX, Map, \
generator_function_with_name_and_home_object_map) \
V(ASYNC_GENERATOR_FUNCTION_MAP_INDEX, Map, async_generator_function_map) \
V(ASYNC_GENERATOR_FUNCTION_WITH_NAME_MAP_INDEX, Map, \
async_generator_function_with_name_map) \
V(ASYNC_GENERATOR_FUNCTION_WITH_HOME_OBJECT_MAP_INDEX, Map, \
async_generator_function_with_home_object_map) \
V(ASYNC_GENERATOR_FUNCTION_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX, Map, \
async_generator_function_with_name_and_home_object_map) \
V(CLASS_FUNCTION_MAP_INDEX, Map, class_function_map) \
V(STRING_FUNCTION_INDEX, JSFunction, string_function) \
V(STRING_FUNCTION_PROTOTYPE_MAP_INDEX, Map, string_function_prototype_map) \
@ -400,7 +385,7 @@ class ScriptContextTable : public FixedArray {
// [ previous ] A pointer to the previous context.
//
// [ extension ] Additional data. This slot is only available when
// extension_bit is set. Check using has_extension.
// ScopeInfo::HasContextExtensionSlot returns true.
//
// For native contexts, it contains the global object.
// For module contexts, it contains the module object.
@ -486,7 +471,7 @@ class Context : public TorqueGeneratedContext<Context, HeapObject> {
SCOPE_INFO_INDEX,
PREVIOUS_INDEX,
// This slot only exists if the extension_flag bit is set.
// This slot only exists if ScopeInfo::HasContextExtensionSlot returns true.
EXTENSION_INDEX,
// These slots are only in native contexts.
@ -624,8 +609,7 @@ class Context : public TorqueGeneratedContext<Context, HeapObject> {
bool* is_sloppy_function_name = nullptr);
static inline int FunctionMapIndex(LanguageMode language_mode,
FunctionKind kind, bool has_shared_name,
bool needs_home_object);
FunctionKind kind, bool has_shared_name);
static int ArrayMapIndex(ElementsKind elements_kind) {
DCHECK(IsFastElementsKind(elements_kind));

View File

@ -31,7 +31,9 @@ enum FunctionKind : uint8_t {
// END constructable functions.
// BEGIN accessors
kGetterFunction,
kStaticGetterFunction,
kSetterFunction,
kStaticSetterFunction,
// END accessors
// BEGIN arrow functions
kArrowFunction,
@ -41,20 +43,25 @@ enum FunctionKind : uint8_t {
kAsyncFunction,
// BEGIN concise methods 1
kAsyncConciseMethod,
kStaticAsyncConciseMethod,
// BEGIN generators
kAsyncConciseGeneratorMethod,
kStaticAsyncConciseGeneratorMethod,
// END concise methods 1
kAsyncGeneratorFunction,
// END async functions
kGeneratorFunction,
// BEGIN concise methods 2
kConciseGeneratorMethod,
kStaticConciseGeneratorMethod,
// END generators
kConciseMethod,
kStaticConciseMethod,
kClassMembersInitializerFunction,
kStaticClassMembersInitializerFunction,
// END concise methods 2
kLastFunctionKind = kClassMembersInitializerFunction,
kLastFunctionKind = kStaticClassMembersInitializerFunction,
};
constexpr int kFunctionKindBitSize = 5;
@ -81,7 +88,7 @@ inline bool IsAsyncGeneratorFunction(FunctionKind kind) {
inline bool IsGeneratorFunction(FunctionKind kind) {
return base::IsInRange(kind, FunctionKind::kAsyncConciseGeneratorMethod,
FunctionKind::kConciseGeneratorMethod);
FunctionKind::kStaticConciseGeneratorMethod);
}
inline bool IsAsyncFunction(FunctionKind kind) {
@ -95,31 +102,33 @@ inline bool IsResumableFunction(FunctionKind kind) {
inline bool IsConciseMethod(FunctionKind kind) {
return base::IsInRange(kind, FunctionKind::kAsyncConciseMethod,
FunctionKind::kAsyncConciseGeneratorMethod) ||
FunctionKind::kStaticAsyncConciseGeneratorMethod) ||
base::IsInRange(kind, FunctionKind::kConciseGeneratorMethod,
FunctionKind::kClassMembersInitializerFunction);
FunctionKind::kStaticClassMembersInitializerFunction);
}
inline bool IsStrictFunctionWithoutPrototype(FunctionKind kind) {
return base::IsInRange(kind, FunctionKind::kGetterFunction,
FunctionKind::kAsyncArrowFunction) ||
base::IsInRange(kind, FunctionKind::kAsyncConciseMethod,
FunctionKind::kAsyncConciseGeneratorMethod) ||
FunctionKind::kStaticAsyncConciseGeneratorMethod) ||
base::IsInRange(kind, FunctionKind::kConciseGeneratorMethod,
FunctionKind::kClassMembersInitializerFunction);
FunctionKind::kStaticClassMembersInitializerFunction);
}
inline bool IsGetterFunction(FunctionKind kind) {
return kind == FunctionKind::kGetterFunction;
return base::IsInRange(kind, FunctionKind::kGetterFunction,
FunctionKind::kStaticGetterFunction);
}
inline bool IsSetterFunction(FunctionKind kind) {
return kind == FunctionKind::kSetterFunction;
return base::IsInRange(kind, FunctionKind::kSetterFunction,
FunctionKind::kStaticSetterFunction);
}
inline bool IsAccessorFunction(FunctionKind kind) {
return base::IsInRange(kind, FunctionKind::kGetterFunction,
FunctionKind::kSetterFunction);
FunctionKind::kStaticSetterFunction);
}
inline bool IsDefaultConstructor(FunctionKind kind) {
@ -143,7 +152,8 @@ inline bool IsClassConstructor(FunctionKind kind) {
}
inline bool IsClassMembersInitializerFunction(FunctionKind kind) {
return kind == FunctionKind::kClassMembersInitializerFunction;
return base::IsInRange(kind, FunctionKind::kClassMembersInitializerFunction,
FunctionKind::kStaticClassMembersInitializerFunction);
}
inline bool IsConstructable(FunctionKind kind) {
@ -151,6 +161,21 @@ inline bool IsConstructable(FunctionKind kind) {
FunctionKind::kDerivedConstructor);
}
inline bool IsStatic(FunctionKind kind) {
switch (kind) {
case FunctionKind::kStaticGetterFunction:
case FunctionKind::kStaticSetterFunction:
case FunctionKind::kStaticConciseMethod:
case FunctionKind::kStaticConciseGeneratorMethod:
case FunctionKind::kStaticAsyncConciseMethod:
case FunctionKind::kStaticAsyncConciseGeneratorMethod:
case FunctionKind::kStaticClassMembersInitializerFunction:
return true;
default:
return false;
}
}
inline const char* FunctionKind2String(FunctionKind kind) {
switch (kind) {
case FunctionKind::kNormalFunction:
@ -161,14 +186,20 @@ inline const char* FunctionKind2String(FunctionKind kind) {
return "GeneratorFunction";
case FunctionKind::kConciseMethod:
return "ConciseMethod";
case FunctionKind::kStaticConciseMethod:
return "StaticConciseMethod";
case FunctionKind::kDerivedConstructor:
return "DerivedConstructor";
case FunctionKind::kBaseConstructor:
return "BaseConstructor";
case FunctionKind::kGetterFunction:
return "GetterFunction";
case FunctionKind::kStaticGetterFunction:
return "StaticGetterFunction";
case FunctionKind::kSetterFunction:
return "SetterFunction";
case FunctionKind::kStaticSetterFunction:
return "StaticSetterFunction";
case FunctionKind::kAsyncFunction:
return "AsyncFunction";
case FunctionKind::kModule:
@ -177,6 +208,8 @@ inline const char* FunctionKind2String(FunctionKind kind) {
return "AsyncModule";
case FunctionKind::kClassMembersInitializerFunction:
return "ClassMembersInitializerFunction";
case FunctionKind::kStaticClassMembersInitializerFunction:
return "StaticClassMembersInitializerFunction";
case FunctionKind::kDefaultBaseConstructor:
return "DefaultBaseConstructor";
case FunctionKind::kDefaultDerivedConstructor:
@ -185,10 +218,16 @@ inline const char* FunctionKind2String(FunctionKind kind) {
return "AsyncArrowFunction";
case FunctionKind::kAsyncConciseMethod:
return "AsyncConciseMethod";
case FunctionKind::kStaticAsyncConciseMethod:
return "StaticAsyncConciseMethod";
case FunctionKind::kConciseGeneratorMethod:
return "ConciseGeneratorMethod";
case FunctionKind::kStaticConciseGeneratorMethod:
return "StaticConciseGeneratorMethod";
case FunctionKind::kAsyncConciseGeneratorMethod:
return "AsyncConciseGeneratorMethod";
case FunctionKind::kStaticAsyncConciseGeneratorMethod:
return "StaticAsyncConciseGeneratorMethod";
case FunctionKind::kAsyncGeneratorFunction:
return "AsyncGeneratorFunction";
}

View File

@ -63,8 +63,7 @@ class JSFunction : public JSFunctionOrBoundFunction {
static const int kLengthDescriptorIndex = 0;
static const int kNameDescriptorIndex = 1;
// Home object descriptor index when function has a [[HomeObject]] slot.
static const int kMaybeHomeObjectDescriptorIndex = 2;
// Fast binding requires length and name accessors.
static const int kMinDescriptorsForFastBind = 2;

View File

@ -626,14 +626,6 @@ Handle<ClassBoilerplate> ClassBoilerplate::BuildClassBoilerplate(
static_desc.AddConstant(isolate, factory->prototype_string(),
factory->function_prototype_accessor(), attribs);
}
if (FunctionLiteral::NeedsHomeObject(expr->constructor())) {
PropertyAttributes attribs =
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
Handle<Object> value(
Smi::FromInt(ClassBoilerplate::kPrototypeArgumentIndex), isolate);
static_desc.AddConstant(isolate, factory->home_object_symbol(), value,
attribs);
}
{
Handle<ClassPositions> class_positions = factory->NewClassPositions(
expr->start_position(), expr->end_position());

View File

@ -1599,13 +1599,9 @@ void EnsureInitialMap(Isolate* isolate, Handle<Map> map) {
// Same holds for GeneratorFunction and its initial map.
*map == *isolate->generator_function_map() ||
*map == *isolate->generator_function_with_name_map() ||
*map == *isolate->generator_function_with_home_object_map() ||
*map == *isolate->generator_function_with_name_and_home_object_map() ||
// AsyncFunction has Null as a constructor.
*map == *isolate->async_function_map() ||
*map == *isolate->async_function_with_name_map() ||
*map == *isolate->async_function_with_home_object_map() ||
*map == *isolate->async_function_with_name_and_home_object_map());
*map == *isolate->async_function_with_name_map());
#endif
// Initial maps must not contain descriptors in the descriptors array
// that do not belong to the map.

View File

@ -52,9 +52,6 @@ class ScopeInfo : public FixedArray {
// True if this scope is a (var) declaration scope.
bool is_declaration_scope() const;
// True if this scope is a class scope.
bool is_class_scope() const;
// Does this scope make a sloppy eval call?
bool SloppyEvalCanExtendVars() const;
@ -80,7 +77,7 @@ class ScopeInfo : public FixedArray {
// Does this scope has class brand (for private methods)?
bool HasClassBrand() const;
// Does this scope contains a saved class variable context local slot index
// Does this scope contain a saved class variable context local slot index
// for checking receivers of static private methods?
bool HasSavedClassVariableIndex() const;

View File

@ -304,17 +304,6 @@ bool SharedFunctionInfo::is_wrapped() const {
return syntax_kind() == FunctionSyntaxKind::kWrapped;
}
bool SharedFunctionInfo::needs_home_object() const {
return NeedsHomeObjectBit::decode(flags());
}
void SharedFunctionInfo::set_needs_home_object(bool value) {
int hints = flags();
hints = NeedsHomeObjectBit::update(hints, value);
set_flags(hints);
UpdateFunctionMapIndex();
}
bool SharedFunctionInfo::construct_as_builtin() const {
return ConstructAsBuiltinBit::decode(flags());
}
@ -358,8 +347,8 @@ void SharedFunctionInfo::clear_padding() {
}
void SharedFunctionInfo::UpdateFunctionMapIndex() {
int map_index = Context::FunctionMapIndex(
language_mode(), kind(), HasSharedName(), needs_home_object());
int map_index =
Context::FunctionMapIndex(language_mode(), kind(), HasSharedName());
set_function_map_index(map_index);
}

View File

@ -452,7 +452,6 @@ void SharedFunctionInfo::InitFromFunctionLiteral(
shared_info->set_function_literal_id(lit->function_literal_id());
// FunctionKind must have already been set.
DCHECK(lit->kind() == shared_info->kind());
shared_info->set_needs_home_object(lit->scope()->NeedsHomeObject());
DCHECK_IMPLIES(lit->requires_instance_members_initializer(),
IsClassConstructor(lit->kind()));
shared_info->set_requires_instance_members_initializer(

View File

@ -622,11 +622,6 @@ class SharedFunctionInfo
STATIC_ASSERT(FunctionSyntaxKind::kLastFunctionSyntaxKind <=
FunctionSyntaxKindBits::kMax);
// Indicates that this function uses a super property (or an eval that may
// use a super property).
// This is needed to set up the [[HomeObject]] on the function instance.
inline bool needs_home_object() const;
// Sets the bytecode in {shared}'s DebugInfo as the bytecode to
// be returned by following calls to GetActiveBytecodeArray. Stores a
// reference to the original bytecode in the DebugInfo.
@ -660,8 +655,6 @@ class SharedFunctionInfo
inline void set_kind(FunctionKind kind);
inline void set_needs_home_object(bool value);
inline uint16_t get_property_estimate_from_literal(FunctionLiteral* literal);
template <typename Impl>

View File

@ -27,7 +27,6 @@ bitfield struct SharedFunctionInfoFlags extends uint32 {
is_class_constructor: bool: 1 bit;
has_duplicate_parameters: bool: 1 bit;
allow_lazy_compilation: bool: 1 bit;
needs_home_object: bool: 1 bit;
is_asm_wasm_broken: bool: 1 bit;
function_map_index: uint32: 5 bit;
disabled_optimization_reason: BailoutReason: 4 bit;

View File

@ -623,6 +623,8 @@ class ParserBase {
DeclarationScope* static_fields_scope;
DeclarationScope* instance_members_scope;
int computed_field_count;
Variable* home_object_variable = nullptr;
Variable* static_home_object_variable = nullptr;
};
enum class PropertyPosition { kObjectLiteral, kClassLiteral };
@ -781,6 +783,12 @@ class ParserBase {
return zone()->template New<ClassScope>(zone(), parent, is_anonymous);
}
Scope* NewBlockScopeForObjectLiteral() {
Scope* scope = NewScope(BLOCK_SCOPE);
scope->set_is_block_scope_for_object_literal();
return scope;
}
Scope* NewScope(ScopeType scope_type) const {
return NewScopeWithParent(scope(), scope_type);
}
@ -1371,10 +1379,13 @@ class ParserBase {
return true;
}
FunctionKind FunctionKindForImpl(bool is_method, ParseFunctionFlags flags) {
enum SubFunctionKind { kFunction, kNonStaticMethod, kStaticMethod };
FunctionKind FunctionKindForImpl(SubFunctionKind sub_function_kind,
ParseFunctionFlags flags) {
static const FunctionKind kFunctionKinds[][2][2] = {
{
// is_method=false
// SubFunctionKind::kNormalFunction
{// is_generator=false
FunctionKind::kNormalFunction, FunctionKind::kAsyncFunction},
{// is_generator=true
@ -1382,26 +1393,35 @@ class ParserBase {
FunctionKind::kAsyncGeneratorFunction},
},
{
// is_method=true
// SubFunctionKind::kNonStaticMethod
{// is_generator=false
FunctionKind::kConciseMethod, FunctionKind::kAsyncConciseMethod},
{// is_generator=true
FunctionKind::kConciseGeneratorMethod,
FunctionKind::kAsyncConciseGeneratorMethod},
},
{
// SubFunctionKind::kStaticMethod
{// is_generator=false
FunctionKind::kStaticConciseMethod,
FunctionKind::kStaticAsyncConciseMethod},
{// is_generator=true
FunctionKind::kStaticConciseGeneratorMethod,
FunctionKind::kStaticAsyncConciseGeneratorMethod},
}};
return kFunctionKinds[is_method]
return kFunctionKinds[sub_function_kind]
[(flags & ParseFunctionFlag::kIsGenerator) != 0]
[(flags & ParseFunctionFlag::kIsAsync) != 0];
}
inline FunctionKind FunctionKindFor(ParseFunctionFlags flags) {
const bool kIsMethod = false;
return FunctionKindForImpl(kIsMethod, flags);
return FunctionKindForImpl(SubFunctionKind::kFunction, flags);
}
inline FunctionKind MethodKindFor(ParseFunctionFlags flags) {
const bool kIsMethod = true;
return FunctionKindForImpl(kIsMethod, flags);
inline FunctionKind MethodKindFor(bool is_static, ParseFunctionFlags flags) {
return FunctionKindForImpl(is_static ? SubFunctionKind::kStaticMethod
: SubFunctionKind::kNonStaticMethod,
flags);
}
// Keep track of eval() calls since they disable all local variable
@ -1505,6 +1525,8 @@ class ParserBase {
// Parser base's protected field members.
Scope* scope_; // Scope stack.
// Stack of scopes for object literals we're currently parsing.
Scope* object_literal_scope_ = nullptr;
Scope* original_scope_; // The top scope for the current parsing item.
FunctionState* function_state_; // Function state stack.
v8::Extension* extension_;
@ -2332,7 +2354,8 @@ ParserBase<Impl>::ParseClassPropertyDefinition(ClassInfo* class_info,
&class_info->has_seen_constructor);
}
FunctionKind kind = MethodKindFor(prop_info->function_flags);
FunctionKind kind =
MethodKindFor(prop_info->is_static, prop_info->function_flags);
if (!prop_info->is_static && impl()->IsConstructor(prop_info->name)) {
class_info->has_seen_constructor = true;
@ -2369,8 +2392,14 @@ ParserBase<Impl>::ParseClassPropertyDefinition(ClassInfo* class_info,
prop_info->name, name_expression->position());
}
FunctionKind kind = is_get ? FunctionKind::kGetterFunction
: FunctionKind::kSetterFunction;
FunctionKind kind;
if (prop_info->is_static) {
kind = is_get ? FunctionKind::kStaticGetterFunction
: FunctionKind::kStaticSetterFunction;
} else {
kind = is_get ? FunctionKind::kGetterFunction
: FunctionKind::kSetterFunction;
}
FunctionLiteralT value = impl()->ParseFunctionLiteral(
prop_info->name, scanner()->location(), kSkipFunctionNameCheck, kind,
@ -2406,10 +2435,12 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseMemberInitializer(
DeclarationScope* initializer_scope =
is_static ? class_info->static_fields_scope
: class_info->instance_members_scope;
FunctionKind function_kind =
is_static ? FunctionKind::kStaticClassMembersInitializerFunction
: FunctionKind::kClassMembersInitializerFunction;
if (initializer_scope == nullptr) {
initializer_scope =
NewFunctionScope(FunctionKind::kClassMembersInitializerFunction);
initializer_scope = NewFunctionScope(function_kind);
// TODO(gsathya): Make scopes be non contiguous.
initializer_scope->set_start_position(beg_pos);
initializer_scope->SetLanguageMode(LanguageMode::kStrict);
@ -2553,7 +2584,13 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ParsePropertyInfo* prop_info,
Scanner::Location(next_loc.beg_pos, end_position()),
MessageTemplate::kInvalidDestructuringTarget);
FunctionKind kind = MethodKindFor(function_flags);
std::unique_ptr<BlockState> block_state;
if (object_literal_scope_ != nullptr) {
DCHECK_EQ(object_literal_scope_->outer_scope(), scope_);
block_state.reset(new BlockState(&scope_, object_literal_scope_));
}
constexpr bool kIsStatic = false;
FunctionKind kind = MethodKindFor(kIsStatic, function_flags);
ExpressionT value = impl()->ParseFunctionLiteral(
name, scanner()->location(), kSkipFunctionNameCheck, kind,
@ -2584,6 +2621,12 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ParsePropertyInfo* prop_info,
factory()->NewStringLiteral(name, name_expression->position());
}
std::unique_ptr<BlockState> block_state;
if (object_literal_scope_ != nullptr) {
DCHECK_EQ(object_literal_scope_->outer_scope(), scope_);
block_state.reset(new BlockState(&scope_, object_literal_scope_));
}
FunctionKind kind = is_get ? FunctionKind::kGetterFunction
: FunctionKind::kSetterFunction;
@ -2628,6 +2671,11 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral() {
Consume(Token::LBRACE);
AccumulationScope accumulation_scope(expression_scope());
// If methods appear inside the object literal, we'll enter this scope.
Scope* block_scope = NewBlockScopeForObjectLiteral();
block_scope->set_start_position(pos);
BlockState object_literal_scope_state(&object_literal_scope_, block_scope);
while (!Check(Token::RBRACE)) {
FuncNameInferrerState fni_state(&fni_);
@ -2660,6 +2708,15 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral() {
fni_.Infer();
}
Variable* home_object = nullptr;
if (block_scope->NeedsHomeObject()) {
home_object = block_scope->DeclareHomeObjectVariable(ast_value_factory());
block_scope->set_end_position(end_position());
} else {
block_scope = block_scope->FinalizeBlockScope();
DCHECK_NULL(block_scope);
}
// In pattern rewriter, we rewrite rest property to call out to a
// runtime function passing all the other properties as arguments to
// this runtime function. Here, we make sure that the number of
@ -2670,8 +2727,9 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral() {
MessageTemplate::kTooManyArguments);
}
return impl()->InitializeObjectLiteral(factory()->NewObjectLiteral(
properties, number_of_boilerplate_properties, pos, has_rest_property));
return impl()->InitializeObjectLiteral(
factory()->NewObjectLiteral(properties, number_of_boilerplate_properties,
pos, has_rest_property, home_object));
}
template <typename Impl>
@ -3623,7 +3681,8 @@ ParserBase<Impl>::ParseSuperExpression() {
impl()->ReportMessage(MessageTemplate::kOptionalChainingNoSuper);
return impl()->FailureExpression();
}
scope->RecordSuperPropertyUsage();
Scope* home_object_scope = scope->GetHomeObjectScope();
home_object_scope->set_needs_home_object();
UseThis();
return impl()->NewSuperPropertyReference(pos);
}
@ -4533,6 +4592,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
BlockState block_state(&scope_, class_scope);
RaiseLanguageMode(LanguageMode::kStrict);
BlockState object_literal_scope_state(&object_literal_scope_, nullptr);
ClassInfo class_info(this);
class_info.is_anonymous = is_anonymous;
@ -4619,6 +4680,13 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
ast_value_factory(), IsStaticFlag::kNotStatic, kNoSourcePosition);
}
if (class_scope->NeedsHomeObject()) {
class_info.home_object_variable =
class_scope->DeclareHomeObjectVariable(ast_value_factory());
class_info.static_home_object_variable =
class_scope->DeclareStaticHomeObjectVariable(ast_value_factory());
}
bool should_save_class_variable_index =
class_scope->should_save_class_variable_index();
if (!is_anonymous || should_save_class_variable_index) {

View File

@ -281,14 +281,14 @@ Expression* Parser::NewThrowError(Runtime::FunctionId id,
}
Expression* Parser::NewSuperPropertyReference(int pos) {
// this_function[home_object_symbol]
VariableProxy* this_function_proxy =
NewUnresolved(ast_value_factory()->this_function_string(), pos);
Expression* home_object_symbol_literal = factory()->NewSymbolLiteral(
AstSymbol::kHomeObjectSymbol, kNoSourcePosition);
Expression* home_object = factory()->NewProperty(
this_function_proxy, home_object_symbol_literal, pos);
return factory()->NewSuperPropertyReference(home_object, pos);
const AstRawString* home_object_name;
if (IsStatic(scope()->GetReceiverScope()->function_kind())) {
home_object_name = ast_value_factory_->dot_static_home_object_string();
} else {
home_object_name = ast_value_factory_->dot_home_object_string();
}
return factory()->NewSuperPropertyReference(
NewUnresolved(home_object_name, pos), pos);
}
Expression* Parser::NewSuperCallReference(int pos) {
@ -2728,7 +2728,7 @@ bool Parser::SkipFunction(const AstRawString* function_name, FunctionKind kind,
Expect(Token::RBRACE);
SetLanguageMode(function_scope, language_mode);
if (uses_super_property) {
function_scope->RecordSuperPropertyUsage();
function_scope->GetHomeObjectScope()->set_needs_home_object();
}
SkipFunctionLiterals(num_inner_functions);
function_scope->ResetAfterPreparsing(ast_value_factory_, false);
@ -3092,8 +3092,7 @@ void Parser::DeclarePublicClassMethod(const AstRawString* class_name,
FunctionLiteral* Parser::CreateInitializerFunction(
const char* name, DeclarationScope* scope,
ZonePtrList<ClassLiteral::Property>* fields) {
DCHECK_EQ(scope->function_kind(),
FunctionKind::kClassMembersInitializerFunction);
DCHECK(IsClassMembersInitializerFunction(scope->function_kind()));
// function() { .. class fields initializer .. }
ScopedPtrList<Statement> statements(pointer_buffer());
InitializeClassMembersStatement* stmt =
@ -3168,7 +3167,8 @@ Expression* Parser::RewriteClassLiteral(ClassScope* block_scope,
static_fields_initializer, instance_members_initializer_function, pos,
end_pos, class_info->has_name_static_property,
class_info->has_static_computed_names, class_info->is_anonymous,
class_info->has_private_methods);
class_info->has_private_methods, class_info->home_object_variable,
class_info->static_home_object_variable);
AddFunctionForNameInference(class_info->constructor);
return class_literal;

View File

@ -39,7 +39,7 @@ using LengthEqualsParametersField = HasDataField::Next<bool, 1>;
using NumberOfParametersField = LengthEqualsParametersField::Next<uint16_t, 16>;
using LanguageField = base::BitField8<LanguageMode, 0, 1>;
using UsesSuperField = LanguageField::Next<bool, 1>;
using MaybeUsesSuperField = LanguageField::Next<bool, 1>;
STATIC_ASSERT(LanguageModeSize <= LanguageField::kNumValues);
} // namespace
@ -304,9 +304,13 @@ bool PreparseDataBuilder::SaveDataForSkippableFunction(
}
byte_data_.WriteVarint32(builder->num_inner_functions_);
Scope* home_object_scope = function_scope->GetHomeObjectScope();
bool maybe_uses_super =
home_object_scope != nullptr && home_object_scope->NeedsHomeObject();
uint8_t language_and_super =
LanguageField::encode(function_scope->language_mode()) |
UsesSuperField::encode(function_scope->NeedsHomeObject());
MaybeUsesSuperField::encode(maybe_uses_super);
byte_data_.WriteQuarter(language_and_super);
return has_data;
}
@ -361,7 +365,7 @@ void PreparseDataBuilder::SaveDataForScope(Scope* scope) {
byte_data_.WriteUint8(scope->scope_type());
#endif
uint8_t eval_and_private_recalc =
uint8_t scope_data_flags =
ScopeSloppyEvalCanExtendVarsBit::encode(
scope->is_declaration_scope() &&
scope->AsDeclarationScope()->sloppy_eval_can_extend_vars()) |
@ -374,7 +378,7 @@ void PreparseDataBuilder::SaveDataForScope(Scope* scope) {
scope->is_class_scope() &&
scope->AsClassScope()->should_save_class_variable_index());
byte_data_.Reserve(kUint8Size);
byte_data_.WriteUint8(eval_and_private_recalc);
byte_data_.WriteUint8(scope_data_flags);
if (scope->is_function_scope()) {
Variable* function = scope->AsDeclarationScope()->function_var();
@ -578,8 +582,8 @@ template <class Data>
ProducedPreparseData*
BaseConsumedPreparseData<Data>::GetDataForSkippableFunction(
Zone* zone, int start_position, int* end_position, int* num_parameters,
int* function_length, int* num_inner_functions, bool* uses_super_property,
LanguageMode* language_mode) {
int* function_length, int* num_inner_functions,
bool* maybe_uses_super_property, LanguageMode* language_mode) {
// The skippable function *must* be the next function in the data. Use the
// start position as a sanity check.
typename ByteData::ReadingScope reading_scope(this);
@ -605,7 +609,7 @@ BaseConsumedPreparseData<Data>::GetDataForSkippableFunction(
uint8_t language_and_super = scope_data_->ReadQuarter();
*language_mode = LanguageMode(LanguageField::decode(language_and_super));
*uses_super_property = UsesSuperField::decode(language_and_super);
*maybe_uses_super_property = MaybeUsesSuperField::decode(language_and_super);
if (!has_data) return nullptr;

View File

@ -567,7 +567,7 @@ class PreParserFactory {
}
PreParserExpression NewObjectLiteral(
const PreParserExpressionList& properties, int boilerplate_properties,
int pos, bool has_rest_property) {
int pos, bool has_rest_property, Variable* home_object = nullptr) {
return PreParserExpression::ObjectLiteral();
}
PreParserExpression NewVariableProxy(void* variable) {

View File

@ -113,11 +113,6 @@ RUNTIME_FUNCTION(Runtime_ThrowNotSuperConstructor) {
return ThrowNotSuperConstructor(isolate, constructor, function);
}
RUNTIME_FUNCTION(Runtime_HomeObjectSymbol) {
DCHECK_EQ(0, args.length());
return ReadOnlyRoots(isolate).home_object_symbol();
}
namespace {
template <typename Dictionary>
@ -134,35 +129,17 @@ Handle<Name> KeyToName<NumberDictionary>(Isolate* isolate, Handle<Object> key) {
return isolate->factory()->NumberToString(key);
}
inline void SetHomeObject(Isolate* isolate, JSFunction method,
JSObject home_object) {
if (method.shared().needs_home_object()) {
const InternalIndex kPropertyIndex(
JSFunction::kMaybeHomeObjectDescriptorIndex);
CHECK_EQ(
method.map().instance_descriptors(kRelaxedLoad).GetKey(kPropertyIndex),
ReadOnlyRoots(isolate).home_object_symbol());
FieldIndex field_index =
FieldIndex::ForDescriptor(method.map(), kPropertyIndex);
method.RawFastPropertyAtPut(field_index, home_object);
}
}
// Gets |index|'th argument which may be a class constructor object, a class
// prototype object or a class method. In the latter case the following
// post-processing may be required:
// 1) set [[HomeObject]] slot to given |home_object| value if the method's
// shared function info indicates that the method requires that;
// 2) set method's name to a concatenation of |name_prefix| and |key| if the
// 1) set method's name to a concatenation of |name_prefix| and |key| if the
// method's shared function info indicates that method does not have a
// shared name.
template <typename Dictionary>
MaybeHandle<Object> GetMethodAndSetHomeObjectAndName(
MaybeHandle<Object> GetMethodAndSetName(
Isolate* isolate,
RuntimeArguments& args, // NOLINT(runtime/references)
Smi index, Handle<JSObject> home_object, Handle<String> name_prefix,
Handle<Object> key) {
Smi index, Handle<String> name_prefix, Handle<Object> key) {
int int_index = index.value();
// Class constructor and prototype values do not require post processing.
@ -172,8 +149,6 @@ MaybeHandle<Object> GetMethodAndSetHomeObjectAndName(
Handle<JSFunction> method = args.at<JSFunction>(int_index);
SetHomeObject(isolate, *method, *home_object);
if (!method->shared().HasSharedName()) {
// TODO(ishell): method does not have a shared name at this point only if
// the key is a computed property name. However, the bytecode generator
@ -189,17 +164,14 @@ MaybeHandle<Object> GetMethodAndSetHomeObjectAndName(
}
// Gets |index|'th argument which may be a class constructor object, a class
// prototype object or a class method. In the latter case the following
// post-processing may be required:
// 1) set [[HomeObject]] slot to given |home_object| value if the method's
// shared function info indicates that the method requires that;
// This is a simplified version of GetMethodWithSharedNameAndSetHomeObject()
// prototype object or a class method.
// This is a simplified version of GetMethodAndSetName()
// function above that is used when it's guaranteed that the method has
// shared name.
Object GetMethodWithSharedNameAndSetHomeObject(
Object GetMethodWithSharedName(
Isolate* isolate,
RuntimeArguments& args, // NOLINT(runtime/references)
Object index, JSObject home_object) {
Object index) {
DisallowGarbageCollection no_gc;
int int_index = Smi::ToInt(index);
@ -209,9 +181,6 @@ Object GetMethodWithSharedNameAndSetHomeObject(
}
Handle<JSFunction> method = args.at<JSFunction>(int_index);
SetHomeObject(isolate, *method, home_object);
DCHECK(method->shared().HasSharedName());
return *method;
}
@ -237,7 +206,6 @@ Handle<Dictionary> ShallowCopyDictionaryTemplate(
template <typename Dictionary>
bool SubstituteValues(Isolate* isolate, Handle<Dictionary> dictionary,
Handle<JSObject> receiver,
RuntimeArguments& args, // NOLINT(runtime/references)
bool* install_name_accessor = nullptr) {
Handle<Name> name_string = isolate->factory()->name_string();
@ -260,9 +228,9 @@ bool SubstituteValues(Isolate* isolate, Handle<Dictionary> dictionary,
Handle<Object> result;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, result,
GetMethodAndSetHomeObjectAndName<Dictionary>(
isolate, args, Smi::cast(tmp), receiver,
isolate->factory()->get_string(), key),
GetMethodAndSetName<Dictionary>(isolate, args, Smi::cast(tmp),
isolate->factory()->get_string(),
key),
false);
pair->set_getter(*result);
}
@ -271,9 +239,9 @@ bool SubstituteValues(Isolate* isolate, Handle<Dictionary> dictionary,
Handle<Object> result;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, result,
GetMethodAndSetHomeObjectAndName<Dictionary>(
isolate, args, Smi::cast(tmp), receiver,
isolate->factory()->set_string(), key),
GetMethodAndSetName<Dictionary>(isolate, args, Smi::cast(tmp),
isolate->factory()->set_string(),
key),
false);
pair->set_setter(*result);
}
@ -281,9 +249,9 @@ bool SubstituteValues(Isolate* isolate, Handle<Dictionary> dictionary,
Handle<Object> result;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, result,
GetMethodAndSetHomeObjectAndName<Dictionary>(
isolate, args, Smi::cast(*value), receiver,
isolate->factory()->empty_string(), key),
GetMethodAndSetName<Dictionary>(isolate, args, Smi::cast(*value),
isolate->factory()->empty_string(),
key),
false);
dictionary->ValueAtPut(i, *result);
}
@ -359,8 +327,7 @@ bool AddDescriptorsByTemplate(
if (details.location() == kDescriptor) {
if (details.kind() == kData) {
if (value.IsSmi()) {
value = GetMethodWithSharedNameAndSetHomeObject(isolate, args, value,
*receiver);
value = GetMethodWithSharedName(isolate, args, value);
}
details = details.CopyWithRepresentation(
value.OptimalRepresentation(isolate));
@ -370,13 +337,11 @@ bool AddDescriptorsByTemplate(
AccessorPair pair = AccessorPair::cast(value);
Object tmp = pair.getter();
if (tmp.IsSmi()) {
pair.set_getter(GetMethodWithSharedNameAndSetHomeObject(
isolate, args, tmp, *receiver));
pair.set_getter(GetMethodWithSharedName(isolate, args, tmp));
}
tmp = pair.setter();
if (tmp.IsSmi()) {
pair.set_setter(GetMethodWithSharedNameAndSetHomeObject(
isolate, args, tmp, *receiver));
pair.set_setter(GetMethodWithSharedName(isolate, args, tmp));
}
}
}
@ -405,7 +370,7 @@ bool AddDescriptorsByTemplate(
LayoutDescriptor::FastPointerLayout());
if (elements_dictionary->NumberOfElements() > 0) {
if (!SubstituteValues<NumberDictionary>(isolate, elements_dictionary,
receiver, args)) {
args)) {
return false;
}
map->set_elements_kind(DICTIONARY_ELEMENTS);
@ -480,8 +445,8 @@ bool AddDescriptorsByTemplate(
}
// Replace all indices with proper methods.
if (!SubstituteValues<Dictionary>(isolate, properties_dictionary, receiver,
args, &install_name_accessor)) {
if (!SubstituteValues<Dictionary>(isolate, properties_dictionary, args,
&install_name_accessor)) {
return false;
}
if (install_name_accessor) {
@ -498,7 +463,7 @@ bool AddDescriptorsByTemplate(
if (elements_dictionary->NumberOfElements() > 0) {
if (!SubstituteValues<NumberDictionary>(isolate, elements_dictionary,
receiver, args)) {
args)) {
return false;
}
map->set_elements_kind(DICTIONARY_ELEMENTS);

View File

@ -82,7 +82,6 @@ namespace internal {
#define FOR_EACH_INTRINSIC_CLASSES(F, I) \
F(DefineClass, -1 /* >= 3 */, 1) \
F(HomeObjectSymbol, 0, 1) \
F(LoadFromSuper, 3, 1) \
F(LoadKeyedFromSuper, 3, 1) \
F(StoreKeyedToSuper, 4, 1) \

View File

@ -20,25 +20,22 @@ snippet: "
test();
})();
"
frame size: 6
frame size: 5
parameter count: 1
bytecode array length: 33
bytecode array length: 27
bytecodes: [
B(Mov), R(closure), R(0),
/* 104 S> */ B(LdaConstant), U8(0),
/* 111 E> */ B(LdaKeyedProperty), R(closure), U8(1),
/* 104 S> */ B(LdaImmutableCurrentContextSlot), U8(2),
B(Star), R(3),
B(LdaConstant), U8(0),
B(Star), R(4),
B(LdaConstant), U8(1),
B(Star), R(5),
B(Mov), R(this), R(3),
/* 117 E> */ B(CallRuntime), U16(Runtime::kLoadFromSuper), R(3), U8(3),
B(Star), R(1),
/* 117 E> */ B(CallAnyReceiver), R(1), R(this), U8(1), U8(3),
B(Mov), R(this), R(2),
/* 117 E> */ B(CallRuntime), U16(Runtime::kLoadFromSuper), R(2), U8(3),
B(Star), R(0),
/* 117 E> */ B(CallAnyReceiver), R(0), R(this), U8(1), U8(1),
/* 126 E> */ B(AddSmi), I8(1), U8(0),
/* 130 S> */ B(Return),
]
constant pool: [
SYMBOL_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["method"],
]
handlers: [
@ -59,31 +56,27 @@ snippet: "
test();
})();
"
frame size: 5
frame size: 4
parameter count: 1
bytecode array length: 46
bytecode array length: 37
bytecodes: [
B(Mov), R(closure), R(0),
/* 130 S> */ B(LdaConstant), U8(0),
/* 130 E> */ B(LdaKeyedProperty), R(closure), U8(0),
/* 130 S> */ B(LdaImmutableCurrentContextSlot), U8(2),
B(Star), R(1),
B(LdaConstant), U8(0),
B(Star), R(2),
B(LdaConstant), U8(1),
B(Star), R(3),
B(LdaSmi), I8(2),
B(Star), R(4),
B(Mov), R(this), R(1),
/* 138 E> */ B(CallRuntime), U16(Runtime::kStoreToSuper), R(1), U8(4),
/* 143 S> */ B(LdaConstant), U8(0),
/* 150 E> */ B(LdaKeyedProperty), R(closure), U8(2),
B(Star), R(2),
B(LdaConstant), U8(1),
B(Star), R(3),
B(Mov), R(this), R(1),
/* 156 E> */ B(CallRuntime), U16(Runtime::kLoadFromSuper), R(1), U8(3),
B(Mov), R(this), R(0),
/* 138 E> */ B(CallRuntime), U16(Runtime::kStoreToSuper), R(0), U8(4),
/* 143 S> */ B(LdaImmutableCurrentContextSlot), U8(2),
B(Star), R(1),
B(LdaConstant), U8(0),
B(Star), R(2),
B(Mov), R(this), R(0),
/* 156 E> */ B(CallRuntime), U16(Runtime::kLoadFromSuper), R(0), U8(3),
/* 158 S> */ B(Return),
]
constant pool: [
SYMBOL_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["x"],
]
handlers: [

View File

@ -276,11 +276,12 @@ bytecodes: [
B(Mov), R(3), R(6),
B(Mov), R(0), R(7),
B(CallRuntime), U16(Runtime::kDefineClass), R(5), U8(3),
B(StaCurrentContextSlot), U8(4),
B(Star), R(5),
B(Ldar), R(6),
B(StaCurrentContextSlot), U8(5),
B(CreateClosure), U8(8), U8(3), U8(2),
B(Star), R(6),
B(Ldar), R(5),
B(StaNamedProperty), R(6), U8(9), U8(0),
B(LdaNull),
B(Star), R(7),
B(CallRuntime), U16(Runtime::kCreatePrivateAccessors), R(6), U8(2),
@ -288,7 +289,7 @@ bytecodes: [
B(PopContext), R(2),
B(Mov), R(3), R(1),
/* 122 S> */ B(Ldar), R(1),
/* 122 E> */ B(Construct), R(1), R(0), U8(0), U8(2),
/* 122 E> */ B(Construct), R(1), R(0), U8(0), U8(0),
B(LdaUndefined),
/* 133 S> */ B(Return),
]
@ -302,7 +303,6 @@ constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE ["C"],
SHARED_FUNCTION_INFO_TYPE,
SHARED_FUNCTION_INFO_TYPE,
SYMBOL_TYPE,
]
handlers: [
]
@ -349,19 +349,20 @@ bytecodes: [
B(Mov), R(3), R(6),
B(Mov), R(0), R(7),
B(CallRuntime), U16(Runtime::kDefineClass), R(5), U8(3),
B(StaCurrentContextSlot), U8(4),
B(Star), R(5),
B(Ldar), R(6),
B(StaCurrentContextSlot), U8(5),
B(LdaNull),
B(Star), R(6),
B(CreateClosure), U8(8), U8(3), U8(2),
B(Star), R(7),
B(Ldar), R(5),
B(StaNamedProperty), R(7), U8(9), U8(0),
B(CallRuntime), U16(Runtime::kCreatePrivateAccessors), R(6), U8(2),
B(StaCurrentContextSlot), U8(2),
B(PopContext), R(2),
B(Mov), R(3), R(1),
/* 126 S> */ B(Ldar), R(1),
/* 126 E> */ B(Construct), R(1), R(0), U8(0), U8(2),
/* 126 E> */ B(Construct), R(1), R(0), U8(0), U8(0),
B(LdaUndefined),
/* 137 S> */ B(Return),
]
@ -375,7 +376,6 @@ constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE ["C"],
SHARED_FUNCTION_INFO_TYPE,
SHARED_FUNCTION_INFO_TYPE,
SYMBOL_TYPE,
]
handlers: [
]

View File

@ -23,17 +23,17 @@ bytecodes: [
B(Star), R(3),
B(CallRuntime), U16(Runtime::kCreatePrivateBrandSymbol), R(3), U8(1),
B(StaCurrentContextSlot), U8(3),
B(CreateClosure), U8(3), U8(0), U8(2),
B(StaCurrentContextSlot), U8(2),
B(LdaTheHole),
B(Star), R(6),
B(CreateClosure), U8(3), U8(0), U8(2),
B(CreateClosure), U8(4), U8(1), U8(2),
B(Star), R(2),
B(LdaConstant), U8(1),
B(Star), R(4),
B(Mov), R(2), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(3),
B(Star), R(4),
B(CreateClosure), U8(4), U8(1), U8(2),
B(StaCurrentContextSlot), U8(2),
B(PopContext), R(1),
B(Mov), R(5), R(0),
B(LdaUndefined),
@ -70,17 +70,17 @@ bytecodes: [
B(Star), R(4),
B(CallRuntime), U16(Runtime::kCreatePrivateBrandSymbol), R(4), U8(1),
B(StaCurrentContextSlot), U8(3),
B(CreateClosure), U8(3), U8(0), U8(2),
B(StaCurrentContextSlot), U8(2),
B(LdaTheHole),
B(Star), R(7),
B(CreateClosure), U8(3), U8(0), U8(2),
B(CreateClosure), U8(4), U8(1), U8(2),
B(Star), R(3),
B(LdaConstant), U8(1),
B(Star), R(5),
B(Mov), R(3), R(6),
B(CallRuntime), U16(Runtime::kDefineClass), R(5), U8(3),
B(Star), R(5),
B(CreateClosure), U8(4), U8(1), U8(2),
B(StaCurrentContextSlot), U8(2),
B(PopContext), R(2),
B(Mov), R(6), R(0),
/* 38 E> */ B(CreateBlockContext), U8(5),
@ -89,7 +89,9 @@ bytecodes: [
B(Star), R(4),
B(CallRuntime), U16(Runtime::kCreatePrivateBrandSymbol), R(4), U8(1),
B(StaCurrentContextSlot), U8(3),
/* 93 E> */ B(CreateClosure), U8(8), U8(2), U8(2),
B(CreateClosure), U8(8), U8(2), U8(2),
B(StaCurrentContextSlot), U8(2),
/* 93 E> */ B(CreateClosure), U8(9), U8(3), U8(2),
B(Star), R(3),
B(LdaConstant), U8(6),
B(Star), R(5),
@ -97,8 +99,6 @@ bytecodes: [
B(Mov), R(0), R(7),
B(CallRuntime), U16(Runtime::kDefineClass), R(5), U8(3),
B(Star), R(5),
B(CreateClosure), U8(9), U8(3), U8(2),
B(StaCurrentContextSlot), U8(2),
B(PopContext), R(2),
B(Mov), R(6), R(1),
B(LdaUndefined),
@ -130,7 +130,7 @@ snippet: "
"
frame size: 8
parameter count: 1
bytecode array length: 97
bytecode array length: 94
bytecodes: [
/* 30 E> */ B(CreateBlockContext), U8(0),
B(PushContext), R(2),
@ -153,21 +153,21 @@ bytecodes: [
B(Star), R(4),
B(CallRuntime), U16(Runtime::kCreatePrivateBrandSymbol), R(4), U8(1),
B(StaCurrentContextSlot), U8(3),
/* 77 E> */ B(CreateClosure), U8(7), U8(2), U8(2),
B(CreateClosure), U8(7), U8(2), U8(2),
B(StaCurrentContextSlot), U8(2),
/* 77 E> */ B(CreateClosure), U8(8), U8(3), U8(2),
B(Star), R(3),
B(LdaConstant), U8(5),
B(Star), R(5),
B(Mov), R(3), R(6),
B(Mov), R(0), R(7),
B(CallRuntime), U16(Runtime::kDefineClass), R(5), U8(3),
B(StaCurrentContextSlot), U8(4),
B(Star), R(5),
B(CreateClosure), U8(8), U8(3), U8(2),
B(StaCurrentContextSlot), U8(2),
B(Star), R(6),
B(Ldar), R(5),
B(StaNamedProperty), R(6), U8(9), U8(0),
B(Ldar), R(6),
B(StaCurrentContextSlot), U8(5),
B(PopContext), R(2),
B(Mov), R(3), R(1),
B(Star), R(1),
B(LdaUndefined),
/* 118 S> */ B(Return),
]
@ -181,7 +181,6 @@ constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE ["C"],
SHARED_FUNCTION_INFO_TYPE,
SHARED_FUNCTION_INFO_TYPE,
SYMBOL_TYPE,
]
handlers: [
]

View File

@ -273,23 +273,24 @@ bytecodes: [
B(Ldar), R(9),
B(StaCurrentContextSlot), U8(3),
B(CallRuntime), U16(Runtime::kDefineClass), R(5), U8(5),
B(StaCurrentContextSlot), U8(4),
B(Star), R(5),
B(Ldar), R(4),
B(StaCurrentContextSlot), U8(5),
B(CreateClosure), U8(22), U8(10), U8(2),
B(Star), R(6),
B(StaNamedProperty), R(4), U8(9), U8(9),
B(CreateClosure), U8(23), U8(11), U8(2),
B(Star), R(8),
B(Ldar), R(4),
B(StaNamedProperty), R(8), U8(24), U8(11),
B(CallProperty0), R(8), R(4), U8(13),
B(CallProperty0), R(8), R(4), U8(11),
B(PopContext), R(3),
B(Mov), R(4), R(2),
/* 456 S> */ B(Ldar), R(0),
/* 456 E> */ B(Construct), R(0), R(0), U8(0), U8(15),
/* 456 E> */ B(Construct), R(0), R(0), U8(0), U8(13),
/* 465 S> */ B(Ldar), R(1),
/* 465 E> */ B(Construct), R(1), R(0), U8(0), U8(17),
/* 465 E> */ B(Construct), R(1), R(0), U8(0), U8(15),
/* 474 S> */ B(Ldar), R(2),
/* 474 E> */ B(Construct), R(2), R(0), U8(0), U8(19),
/* 474 E> */ B(Construct), R(2), R(0), U8(0), U8(17),
B(LdaUndefined),
/* 483 S> */ B(Return),
]
@ -318,7 +319,6 @@ constant pool: [
SHARED_FUNCTION_INFO_TYPE,
SHARED_FUNCTION_INFO_TYPE,
SHARED_FUNCTION_INFO_TYPE,
SYMBOL_TYPE,
]
handlers: [
]

View File

@ -19,17 +19,17 @@ bytecode array length: 40
bytecodes: [
/* 30 E> */ B(CreateBlockContext), U8(0),
B(PushContext), R(1),
B(CreateClosure), U8(2), U8(0), U8(2),
B(StaCurrentContextSlot), U8(2),
B(LdaTheHole),
B(Star), R(5),
B(CreateClosure), U8(2), U8(0), U8(2),
B(CreateClosure), U8(3), U8(1), U8(2),
B(Star), R(2),
B(LdaConstant), U8(1),
B(Star), R(3),
B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(3),
B(Star), R(3),
B(CreateClosure), U8(3), U8(1), U8(2),
B(StaCurrentContextSlot), U8(2),
B(PopContext), R(1),
B(Mov), R(4), R(0),
B(LdaUndefined),
@ -194,19 +194,19 @@ bytecodes: [
B(Star), R(3),
B(CallRuntime), U16(Runtime::kCreatePrivateBrandSymbol), R(3), U8(1),
B(StaCurrentContextSlot), U8(4),
B(CreateClosure), U8(3), U8(0), U8(2),
B(StaCurrentContextSlot), U8(2),
B(CreateClosure), U8(4), U8(1), U8(2),
B(StaCurrentContextSlot), U8(3),
B(LdaTheHole),
B(Star), R(6),
B(CreateClosure), U8(3), U8(0), U8(2),
B(CreateClosure), U8(5), U8(2), U8(2),
B(Star), R(2),
B(LdaConstant), U8(1),
B(Star), R(4),
B(Mov), R(2), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(3),
B(Star), R(4),
B(CreateClosure), U8(4), U8(1), U8(2),
B(StaCurrentContextSlot), U8(2),
B(CreateClosure), U8(5), U8(2), U8(2),
B(StaCurrentContextSlot), U8(3),
B(PopContext), R(1),
B(Mov), R(5), R(0),
B(LdaUndefined),

View File

@ -322,6 +322,7 @@ TEST_FUNCTION_KIND(IsArrowFunction)
bool FunctionKindIsAsyncGeneratorFunction(FunctionKind kind) {
switch (kind) {
case FunctionKind::kAsyncConciseGeneratorMethod:
case FunctionKind::kStaticAsyncConciseGeneratorMethod:
case FunctionKind::kAsyncGeneratorFunction:
return true;
default:
@ -333,7 +334,9 @@ TEST_FUNCTION_KIND(IsAsyncGeneratorFunction)
bool FunctionKindIsGeneratorFunction(FunctionKind kind) {
switch (kind) {
case FunctionKind::kConciseGeneratorMethod:
case FunctionKind::kStaticConciseGeneratorMethod:
case FunctionKind::kAsyncConciseGeneratorMethod:
case FunctionKind::kStaticAsyncConciseGeneratorMethod:
case FunctionKind::kGeneratorFunction:
case FunctionKind::kAsyncGeneratorFunction:
return true;
@ -348,7 +351,9 @@ bool FunctionKindIsAsyncFunction(FunctionKind kind) {
case FunctionKind::kAsyncFunction:
case FunctionKind::kAsyncArrowFunction:
case FunctionKind::kAsyncConciseMethod:
case FunctionKind::kStaticAsyncConciseMethod:
case FunctionKind::kAsyncConciseGeneratorMethod:
case FunctionKind::kStaticAsyncConciseGeneratorMethod:
case FunctionKind::kAsyncGeneratorFunction:
return true;
default:
@ -360,9 +365,13 @@ TEST_FUNCTION_KIND(IsAsyncFunction)
bool FunctionKindIsConciseMethod(FunctionKind kind) {
switch (kind) {
case FunctionKind::kConciseMethod:
case FunctionKind::kStaticConciseMethod:
case FunctionKind::kConciseGeneratorMethod:
case FunctionKind::kStaticConciseGeneratorMethod:
case FunctionKind::kAsyncConciseMethod:
case FunctionKind::kStaticAsyncConciseMethod:
case FunctionKind::kAsyncConciseGeneratorMethod:
case FunctionKind::kStaticAsyncConciseGeneratorMethod:
case FunctionKind::kClassMembersInitializerFunction:
return true;
default:
@ -374,7 +383,9 @@ TEST_FUNCTION_KIND(IsConciseMethod)
bool FunctionKindIsAccessorFunction(FunctionKind kind) {
switch (kind) {
case FunctionKind::kGetterFunction:
case FunctionKind::kStaticGetterFunction:
case FunctionKind::kSetterFunction:
case FunctionKind::kStaticSetterFunction:
return true;
default:
return false;
@ -431,16 +442,22 @@ TEST_FUNCTION_KIND(IsClassConstructor)
bool FunctionKindIsConstructable(FunctionKind kind) {
switch (kind) {
case FunctionKind::kGetterFunction:
case FunctionKind::kStaticGetterFunction:
case FunctionKind::kSetterFunction:
case FunctionKind::kStaticSetterFunction:
case FunctionKind::kArrowFunction:
case FunctionKind::kAsyncArrowFunction:
case FunctionKind::kAsyncFunction:
case FunctionKind::kAsyncConciseMethod:
case FunctionKind::kStaticAsyncConciseMethod:
case FunctionKind::kAsyncConciseGeneratorMethod:
case FunctionKind::kStaticAsyncConciseGeneratorMethod:
case FunctionKind::kAsyncGeneratorFunction:
case FunctionKind::kGeneratorFunction:
case FunctionKind::kConciseGeneratorMethod:
case FunctionKind::kStaticConciseGeneratorMethod:
case FunctionKind::kConciseMethod:
case FunctionKind::kStaticConciseMethod:
case FunctionKind::kClassMembersInitializerFunction:
return false;
default:

View File

@ -1153,12 +1153,12 @@ TEST(ScopeUsesArgumentsSuperThis) {
CHECK_NOT_NULL(scope->AsDeclarationScope()->arguments());
}
if (IsClassConstructor(scope->AsDeclarationScope()->function_kind())) {
CHECK_EQ((source_data[i].expected & SUPER_PROPERTY) != 0 ||
(source_data[i].expected & EVAL) != 0,
scope->AsDeclarationScope()->NeedsHomeObject());
CHECK_IMPLIES((source_data[i].expected & SUPER_PROPERTY) != 0 ||
(source_data[i].expected & EVAL) != 0,
scope->GetHomeObjectScope()->NeedsHomeObject());
} else {
CHECK_EQ((source_data[i].expected & SUPER_PROPERTY) != 0,
scope->AsDeclarationScope()->NeedsHomeObject());
CHECK_IMPLIES((source_data[i].expected & SUPER_PROPERTY) != 0,
scope->GetHomeObjectScope()->NeedsHomeObject());
}
if ((source_data[i].expected & THIS) != 0) {
// Currently the is_used() flag is conservative; all variables in a

View File

@ -72,8 +72,6 @@ function assertAccessorDescriptor(object, name) {
[ID(4294967295)]() { return '4294967295' + super.m(); }
}
assertSame(Derived.prototype, Derived.prototype.a[%HomeObjectSymbol()]);
assertMethodDescriptor(Derived.prototype, "a");
assertMethodDescriptor(Derived.prototype, "b");
assertMethodDescriptor(Derived.prototype, 0);

View File

@ -24,8 +24,6 @@ function ID(x) {
[ID(1)]() { return '1' + super.m(); },
};
assertSame(object, object.a[%HomeObjectSymbol()]);
assertEquals('a proto m', object.a());
assertEquals('b proto m', object.b());
assertEquals('0 proto m', object[0]());

View File

@ -0,0 +1,196 @@
// Copyright 2021 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.
(function TestSuperInObjectLiteralMethod() {
let my_proto = {
  __proto__ : {'x': 'right' },
  m() { return super.x; }
};
let o = {__proto__: my_proto};
assertEquals('right', o.m());
})();
(function TestSuperInObjectLiteralGetter() {
let my_proto = {
  __proto__ : {'x': 'right' },
  get p() { return super.x; }
};
let o = {__proto__: my_proto};
assertEquals('right', o.p);
})();
(function TestSuperInObjectLiteralSetter() {
let read_value;
let my_proto = {
  __proto__ : {'x': 'right' },
  set p(x) { read_value = super.x; }
};
let o = {__proto__: my_proto};
o.p = 'whatever';
assertEquals('right', read_value);
})();
(function TestSuperInObjectLiteralProperty() {
class OuterBase {};
OuterBase.prototype.x = 'right';
class Outer extends OuterBase {
m2() {
let my_proto = {
   __proto__ : {'x': 'wrong' },
   m: () => super.x,
};
let o = {__proto__: my_proto};
return o.m();
}
}
assertEquals('right', (new Outer()).m2());
})();
(function TestMethodScopes() {
let object = { // object literal 1 starts
  __proto__: { // object literal 2 starts
    method1() { return 'right'; }
  }, // object literal 2 ends
  method2() {
    return super.method1();
  }
}; // object literal 1 ends
assertEquals('right', object.method2());
})();
(function TestEvalInObjectLiteral() {
let o = {__proto__: {x: 'right'},
x: 'wrong',
m() {
let r = 0;
eval('r = super.x;');
return r;
}
};
assertEquals('right', o.m());
})();
(function TestEvalInMethod() {
class A {};
A.prototype.x = 'right';
class B extends A {
m() {
let r;
eval('r = super.x;');
return r;
}
};
B.prototype.x = 'wrong';
let b = new B();
assertEquals('right', b.m());
})();
(function TestSuperInsidePropertyInitializer() {
class OuterBase {}
OuterBase.prototype.prop = 'wrong';
OuterBase.prop = 'wrong';
class Outer extends OuterBase {
  m() {
    class A { }
    A.prototype.prop = 'right';
    class B extends A {
      x = () => { return super.prop; };
    }
     B.prototype.prop = 'wrong';
    return (new B()).x();
   }
}
Outer.prototype.prop = 'wrong';
Outer.prop = 'wrong';
assertEquals('right', (new Outer()).m());
})();
(function TestSuperInsideStaticPropertyInitializer() {
class OuterBase {}
OuterBase.prototype.prop = 'wrong';
OuterBase.prop = 'wrong';
class Outer extends OuterBase {
m() {
  class A { }
A.prop = 'right';
A.prototype.prop = 'wrong';
class B extends A {
static x = super.prop;
}
B.prop = 'wrong';
B.prototype.prop = 'wrong';
return B.x;
}
}
Outer.prototype.prop = 'wrong';
Outer.prop = 'wrong';
assertEquals('right', (new Outer).m());
})();
(function TestSuperInsideStaticPropertyInitializer2() {
class A extends class {
a() { return 'wrong'; }
} {
m() {
class C extends class {
static a() { return 'right'; }
} {
static static_prop = super.a;
};
return C.static_prop;
}
};
assertEquals('right', (new A()).m()());
})();
(function TestSuperInsideExtends() {
class C extends class {
static a = 'right';
} {
static m = class D extends new Proxy(function f() {},
{get:(t, k) => {
if (k == "prototype") {
return Function.prototype;
}
return super.a;
}
}) {}
};
assertEquals('right', C.m.a);
})();
// Same as the previous test but without a Proxy.
(function TestSuperInsideExtends2() {
function f(x) {
  function A() { }
  A.x = x;
  return A;
}
class B {};
B.a = 'right';
// How to write "super" inside the extends clause? The "class extends value"
// needs to be a constructor.
class C extends B {
  static m = class D extends f({m2: () => { return super.a;}}) { }
}
// C.m is a class. Its "parent class" is a function (returned by f). C.m.x
// binds to the parent's x, which is whatever we passed as a param to f.
// In this case, it's an object which has a property m2.
// Since m2 is an arrow function, and not a method, "super" inside it
// doesn't bind to the object where m2 is defined, but outside.
assertEquals('right', C.m.x.m2());
})();

View File

@ -4,59 +4,6 @@
// Flags: --allow-natives-syntax
(function TestHomeObject() {
var object = {
method() {
return super.method();
},
get getter() {
return super.getter;
},
set setter(v) {
super.setter = v;
},
get accessor() {
return super.accessor;
},
set accessor(v) {
super.accessor = v;
},
methodNoSuper() {},
get getterNoSuper() {},
set setterNoSuper(v) {},
get accessorNoSuper() {},
set accessorNoSuper(v) {},
propertyNoSuper: function() {},
propertyWithParenNoSuper: (function() {}),
propertyWithParensNoSuper: ((function() {}))
};
assertEquals(object, object.method[%HomeObjectSymbol()]);
var desc = Object.getOwnPropertyDescriptor(object, 'getter');
assertEquals(object, desc.get[%HomeObjectSymbol()]);
desc = Object.getOwnPropertyDescriptor(object, 'setter');
assertEquals(object, desc.set[%HomeObjectSymbol()]);
desc = Object.getOwnPropertyDescriptor(object, 'accessor');
assertEquals(object, desc.get[%HomeObjectSymbol()]);
assertEquals(object, desc.set[%HomeObjectSymbol()]);
assertEquals(undefined, object.methodNoSuper[%HomeObjectSymbol()]);
desc = Object.getOwnPropertyDescriptor(object, 'getterNoSuper');
assertEquals(undefined, desc.get[%HomeObjectSymbol()]);
desc = Object.getOwnPropertyDescriptor(object, 'setterNoSuper');
assertEquals(undefined, desc.set[%HomeObjectSymbol()]);
desc = Object.getOwnPropertyDescriptor(object, 'accessorNoSuper');
assertEquals(undefined, desc.get[%HomeObjectSymbol()]);
assertEquals(undefined, desc.set[%HomeObjectSymbol()]);
assertEquals(undefined, object.propertyNoSuper[%HomeObjectSymbol()]);
assertEquals(undefined, object.propertyWithParenNoSuper[%HomeObjectSymbol()]);
assertEquals(undefined,
object.propertyWithParensNoSuper[%HomeObjectSymbol()]);
})();
(function TestMethod() {
var object = {
__proto__: {

View File

@ -305,68 +305,68 @@ KNOWN_MAPS = {
("read_only_space", 0x0314d): (67, "BasicBlockCountersMarkerMap"),
("read_only_space", 0x03191): (87, "ArrayBoilerplateDescriptionMap"),
("read_only_space", 0x03279): (99, "InterceptorInfoMap"),
("read_only_space", 0x053a5): (72, "PromiseFulfillReactionJobTaskMap"),
("read_only_space", 0x053cd): (73, "PromiseRejectReactionJobTaskMap"),
("read_only_space", 0x053f5): (74, "CallableTaskMap"),
("read_only_space", 0x0541d): (75, "CallbackTaskMap"),
("read_only_space", 0x05445): (76, "PromiseResolveThenableJobTaskMap"),
("read_only_space", 0x0546d): (79, "FunctionTemplateInfoMap"),
("read_only_space", 0x05495): (80, "ObjectTemplateInfoMap"),
("read_only_space", 0x054bd): (81, "AccessCheckInfoMap"),
("read_only_space", 0x054e5): (82, "AccessorInfoMap"),
("read_only_space", 0x0550d): (83, "AccessorPairMap"),
("read_only_space", 0x05535): (84, "AliasedArgumentsEntryMap"),
("read_only_space", 0x0555d): (85, "AllocationMementoMap"),
("read_only_space", 0x05585): (88, "AsmWasmDataMap"),
("read_only_space", 0x055ad): (89, "AsyncGeneratorRequestMap"),
("read_only_space", 0x055d5): (90, "BreakPointMap"),
("read_only_space", 0x055fd): (91, "BreakPointInfoMap"),
("read_only_space", 0x05625): (92, "CachedTemplateObjectMap"),
("read_only_space", 0x0564d): (94, "ClassPositionsMap"),
("read_only_space", 0x05675): (95, "DebugInfoMap"),
("read_only_space", 0x0569d): (98, "FunctionTemplateRareDataMap"),
("read_only_space", 0x056c5): (100, "InterpreterDataMap"),
("read_only_space", 0x056ed): (101, "ModuleRequestMap"),
("read_only_space", 0x05715): (102, "PromiseCapabilityMap"),
("read_only_space", 0x0573d): (103, "PromiseReactionMap"),
("read_only_space", 0x05765): (104, "PropertyDescriptorObjectMap"),
("read_only_space", 0x0578d): (105, "PrototypeInfoMap"),
("read_only_space", 0x057b5): (106, "ScriptMap"),
("read_only_space", 0x057dd): (107, "SourceTextModuleInfoEntryMap"),
("read_only_space", 0x05805): (108, "StackFrameInfoMap"),
("read_only_space", 0x0582d): (109, "StackTraceFrameMap"),
("read_only_space", 0x05855): (110, "TemplateObjectDescriptionMap"),
("read_only_space", 0x0587d): (111, "Tuple2Map"),
("read_only_space", 0x058a5): (112, "WasmExceptionTagMap"),
("read_only_space", 0x058cd): (113, "WasmExportedFunctionDataMap"),
("read_only_space", 0x058f5): (114, "WasmIndirectFunctionTableMap"),
("read_only_space", 0x0591d): (115, "WasmJSFunctionDataMap"),
("read_only_space", 0x05945): (134, "SloppyArgumentsElementsMap"),
("read_only_space", 0x0596d): (151, "DescriptorArrayMap"),
("read_only_space", 0x05995): (156, "UncompiledDataWithoutPreparseDataMap"),
("read_only_space", 0x059bd): (155, "UncompiledDataWithPreparseDataMap"),
("read_only_space", 0x059e5): (171, "OnHeapBasicBlockProfilerDataMap"),
("read_only_space", 0x05a0d): (180, "WasmCapiFunctionDataMap"),
("read_only_space", 0x05a35): (168, "InternalClassMap"),
("read_only_space", 0x05a5d): (177, "SmiPairMap"),
("read_only_space", 0x05a85): (176, "SmiBoxMap"),
("read_only_space", 0x05aad): (145, "ExportedSubClassBaseMap"),
("read_only_space", 0x05ad5): (146, "ExportedSubClassMap"),
("read_only_space", 0x05afd): (68, "AbstractInternalClassSubclass1Map"),
("read_only_space", 0x05b25): (69, "AbstractInternalClassSubclass2Map"),
("read_only_space", 0x05b4d): (133, "InternalClassWithSmiElementsMap"),
("read_only_space", 0x05b75): (169, "InternalClassWithStructElementsMap"),
("read_only_space", 0x05b9d): (147, "ExportedSubClass2Map"),
("read_only_space", 0x05bc5): (178, "SortStateMap"),
("read_only_space", 0x05bed): (86, "AllocationSiteWithWeakNextMap"),
("read_only_space", 0x05c15): (86, "AllocationSiteWithoutWeakNextMap"),
("read_only_space", 0x05c3d): (77, "LoadHandler1Map"),
("read_only_space", 0x05c65): (77, "LoadHandler2Map"),
("read_only_space", 0x05c8d): (77, "LoadHandler3Map"),
("read_only_space", 0x05cb5): (78, "StoreHandler0Map"),
("read_only_space", 0x05cdd): (78, "StoreHandler1Map"),
("read_only_space", 0x05d05): (78, "StoreHandler2Map"),
("read_only_space", 0x05d2d): (78, "StoreHandler3Map"),
("read_only_space", 0x053cd): (72, "PromiseFulfillReactionJobTaskMap"),
("read_only_space", 0x053f5): (73, "PromiseRejectReactionJobTaskMap"),
("read_only_space", 0x0541d): (74, "CallableTaskMap"),
("read_only_space", 0x05445): (75, "CallbackTaskMap"),
("read_only_space", 0x0546d): (76, "PromiseResolveThenableJobTaskMap"),
("read_only_space", 0x05495): (79, "FunctionTemplateInfoMap"),
("read_only_space", 0x054bd): (80, "ObjectTemplateInfoMap"),
("read_only_space", 0x054e5): (81, "AccessCheckInfoMap"),
("read_only_space", 0x0550d): (82, "AccessorInfoMap"),
("read_only_space", 0x05535): (83, "AccessorPairMap"),
("read_only_space", 0x0555d): (84, "AliasedArgumentsEntryMap"),
("read_only_space", 0x05585): (85, "AllocationMementoMap"),
("read_only_space", 0x055ad): (88, "AsmWasmDataMap"),
("read_only_space", 0x055d5): (89, "AsyncGeneratorRequestMap"),
("read_only_space", 0x055fd): (90, "BreakPointMap"),
("read_only_space", 0x05625): (91, "BreakPointInfoMap"),
("read_only_space", 0x0564d): (92, "CachedTemplateObjectMap"),
("read_only_space", 0x05675): (94, "ClassPositionsMap"),
("read_only_space", 0x0569d): (95, "DebugInfoMap"),
("read_only_space", 0x056c5): (98, "FunctionTemplateRareDataMap"),
("read_only_space", 0x056ed): (100, "InterpreterDataMap"),
("read_only_space", 0x05715): (101, "ModuleRequestMap"),
("read_only_space", 0x0573d): (102, "PromiseCapabilityMap"),
("read_only_space", 0x05765): (103, "PromiseReactionMap"),
("read_only_space", 0x0578d): (104, "PropertyDescriptorObjectMap"),
("read_only_space", 0x057b5): (105, "PrototypeInfoMap"),
("read_only_space", 0x057dd): (106, "ScriptMap"),
("read_only_space", 0x05805): (107, "SourceTextModuleInfoEntryMap"),
("read_only_space", 0x0582d): (108, "StackFrameInfoMap"),
("read_only_space", 0x05855): (109, "StackTraceFrameMap"),
("read_only_space", 0x0587d): (110, "TemplateObjectDescriptionMap"),
("read_only_space", 0x058a5): (111, "Tuple2Map"),
("read_only_space", 0x058cd): (112, "WasmExceptionTagMap"),
("read_only_space", 0x058f5): (113, "WasmExportedFunctionDataMap"),
("read_only_space", 0x0591d): (114, "WasmIndirectFunctionTableMap"),
("read_only_space", 0x05945): (115, "WasmJSFunctionDataMap"),
("read_only_space", 0x0596d): (134, "SloppyArgumentsElementsMap"),
("read_only_space", 0x05995): (151, "DescriptorArrayMap"),
("read_only_space", 0x059bd): (156, "UncompiledDataWithoutPreparseDataMap"),
("read_only_space", 0x059e5): (155, "UncompiledDataWithPreparseDataMap"),
("read_only_space", 0x05a0d): (171, "OnHeapBasicBlockProfilerDataMap"),
("read_only_space", 0x05a35): (180, "WasmCapiFunctionDataMap"),
("read_only_space", 0x05a5d): (168, "InternalClassMap"),
("read_only_space", 0x05a85): (177, "SmiPairMap"),
("read_only_space", 0x05aad): (176, "SmiBoxMap"),
("read_only_space", 0x05ad5): (145, "ExportedSubClassBaseMap"),
("read_only_space", 0x05afd): (146, "ExportedSubClassMap"),
("read_only_space", 0x05b25): (68, "AbstractInternalClassSubclass1Map"),
("read_only_space", 0x05b4d): (69, "AbstractInternalClassSubclass2Map"),
("read_only_space", 0x05b75): (133, "InternalClassWithSmiElementsMap"),
("read_only_space", 0x05b9d): (169, "InternalClassWithStructElementsMap"),
("read_only_space", 0x05bc5): (147, "ExportedSubClass2Map"),
("read_only_space", 0x05bed): (178, "SortStateMap"),
("read_only_space", 0x05c15): (86, "AllocationSiteWithWeakNextMap"),
("read_only_space", 0x05c3d): (86, "AllocationSiteWithoutWeakNextMap"),
("read_only_space", 0x05c65): (77, "LoadHandler1Map"),
("read_only_space", 0x05c8d): (77, "LoadHandler2Map"),
("read_only_space", 0x05cb5): (77, "LoadHandler3Map"),
("read_only_space", 0x05cdd): (78, "StoreHandler0Map"),
("read_only_space", 0x05d05): (78, "StoreHandler1Map"),
("read_only_space", 0x05d2d): (78, "StoreHandler2Map"),
("read_only_space", 0x05d55): (78, "StoreHandler3Map"),
("map_space", 0x02115): (1057, "ExternalMap"),
("map_space", 0x0213d): (1084, "JSMessageObjectMap"),
("map_space", 0x02165): (181, "WasmRttEqrefMap"),