Commit 4e8c6281 authored by Joyee Cheung's avatar Joyee Cheung Committed by Commit Bot

[class] implement static private methods

This patch refactors the declaration and allocation of the class variable, and
implements static private methods:


- The class variable is declared in the class scope with an explicit
  reference through class_scope->class_variable(). Anonymous classes
  whose class variable may be accessed transitively through static
  private method access use the dot string as the class name. Whether
  the class variable is allocated depending on whether it is used.
  Other references of the class variable in the ClassLiteral AST node
  and the ClassInfo structure are removed in favor of the reference
  through the class scope.
- Previously the class variable was always (stack- or context-)
  allocated if the class is named. Now if the class variable is only
  referenced by name, it's stack allocated. If it's used transitively
  by access to static private methods, or may be used through eval,
  it's context allocated. Therefore we now use 1 less context slots
  in the class context if it's a named class without anyone referencing
  it by name in inner scopes.
- Explicit access to static private methods or potential access to
  static private methods through eval results in forced context
  allocation of the class variables. In those cases, we save its index
  in context locals in the ScopeInfo and deserialize it later, so that
  we can check that the receiver of static private methods is the class
  constructor at run time. This flag is recorded as
  HasSavedClassVariableIndexField in the scope info.
- Classes that need the class variable to be saved due to
  access to static private methods now save a
  ShouldSaveClassVariableIndexField in the preparse data so that the
  bits on the variables can be updated during a reparse. In the case
  of anonymous classes that need the class variables to be saved,
  we also re-declare the class variable after the reparse since
  the inner functions are skipped and we need to rely on the preparse
  data flags to remember declaring it.

Design doc: https://docs.google.com/document/d/1rgGRw5RdzaRrM-GrIMhsn-DLULtADV2dmIdh_iIZxlc/edit

Bug: v8:8330
Change-Id: Idd07803f47614e97ad202de3b7faa9f71105eac5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1781011
Commit-Queue: Joyee Cheung <joyee@igalia.com>
Reviewed-by: 's avatarMythri Alle <mythria@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64219}
parent 939e18fe
...@@ -2490,7 +2490,6 @@ class ClassLiteral final : public Expression { ...@@ -2490,7 +2490,6 @@ class ClassLiteral final : public Expression {
using Property = ClassLiteralProperty; using Property = ClassLiteralProperty;
ClassScope* scope() const { return scope_; } ClassScope* scope() const { return scope_; }
Variable* class_variable() const { return class_variable_; }
Expression* extends() const { return extends_; } Expression* extends() const { return extends_; }
FunctionLiteral* constructor() const { return constructor_; } FunctionLiteral* constructor() const { return constructor_; }
ZonePtrList<Property>* properties() const { return properties_; } ZonePtrList<Property>* properties() const { return properties_; }
...@@ -2521,7 +2520,7 @@ class ClassLiteral final : public Expression { ...@@ -2521,7 +2520,7 @@ class ClassLiteral final : public Expression {
private: private:
friend class AstNodeFactory; friend class AstNodeFactory;
ClassLiteral(ClassScope* scope, Variable* class_variable, Expression* extends, ClassLiteral(ClassScope* scope, Expression* extends,
FunctionLiteral* constructor, ZonePtrList<Property>* properties, FunctionLiteral* constructor, ZonePtrList<Property>* properties,
FunctionLiteral* static_fields_initializer, FunctionLiteral* static_fields_initializer,
FunctionLiteral* instance_members_initializer_function, FunctionLiteral* instance_members_initializer_function,
...@@ -2531,7 +2530,6 @@ class ClassLiteral final : public Expression { ...@@ -2531,7 +2530,6 @@ class ClassLiteral final : public Expression {
: Expression(start_position, kClassLiteral), : Expression(start_position, kClassLiteral),
end_position_(end_position), end_position_(end_position),
scope_(scope), scope_(scope),
class_variable_(class_variable),
extends_(extends), extends_(extends),
constructor_(constructor), constructor_(constructor),
properties_(properties), properties_(properties),
...@@ -2545,7 +2543,6 @@ class ClassLiteral final : public Expression { ...@@ -2545,7 +2543,6 @@ class ClassLiteral final : public Expression {
int end_position_; int end_position_;
ClassScope* scope_; ClassScope* scope_;
Variable* class_variable_;
Expression* extends_; Expression* extends_;
FunctionLiteral* constructor_; FunctionLiteral* constructor_;
ZonePtrList<Property>* properties_; ZonePtrList<Property>* properties_;
...@@ -3259,18 +3256,16 @@ class AstNodeFactory final { ...@@ -3259,18 +3256,16 @@ class AstNodeFactory final {
} }
ClassLiteral* NewClassLiteral( ClassLiteral* NewClassLiteral(
ClassScope* scope, Variable* variable, Expression* extends, ClassScope* scope, Expression* extends, FunctionLiteral* constructor,
FunctionLiteral* constructor,
ZonePtrList<ClassLiteral::Property>* properties, ZonePtrList<ClassLiteral::Property>* properties,
FunctionLiteral* static_fields_initializer, FunctionLiteral* static_fields_initializer,
FunctionLiteral* instance_members_initializer_function, FunctionLiteral* instance_members_initializer_function,
int start_position, int end_position, bool has_name_static_property, int start_position, int end_position, bool has_name_static_property,
bool has_static_computed_names, bool is_anonymous) { bool has_static_computed_names, bool is_anonymous) {
return new (zone_) ClassLiteral( return new (zone_) ClassLiteral(
scope, variable, extends, constructor, properties, scope, extends, constructor, properties, static_fields_initializer,
static_fields_initializer, instance_members_initializer_function, instance_members_initializer_function, start_position, end_position,
start_position, end_position, has_name_static_property, has_name_static_property, has_static_computed_names, is_anonymous);
has_static_computed_names, is_anonymous);
} }
NativeFunctionLiteral* NewNativeFunctionLiteral(const AstRawString* name, NativeFunctionLiteral* NewNativeFunctionLiteral(const AstRawString* name,
......
...@@ -144,13 +144,15 @@ ModuleScope::ModuleScope(Isolate* isolate, Handle<ScopeInfo> scope_info, ...@@ -144,13 +144,15 @@ ModuleScope::ModuleScope(Isolate* isolate, Handle<ScopeInfo> scope_info,
set_language_mode(LanguageMode::kStrict); set_language_mode(LanguageMode::kStrict);
} }
ClassScope::ClassScope(Zone* zone, Scope* outer_scope) ClassScope::ClassScope(Zone* zone, Scope* outer_scope, bool is_anonymous)
: Scope(zone, outer_scope, CLASS_SCOPE), : Scope(zone, outer_scope, CLASS_SCOPE),
rare_data_and_is_parsing_heritage_(nullptr) { rare_data_and_is_parsing_heritage_(nullptr),
is_anonymous_class_(is_anonymous) {
set_language_mode(LanguageMode::kStrict); set_language_mode(LanguageMode::kStrict);
} }
ClassScope::ClassScope(Zone* zone, AstValueFactory* ast_value_factory, ClassScope::ClassScope(Isolate* isolate, Zone* zone,
AstValueFactory* ast_value_factory,
Handle<ScopeInfo> scope_info) Handle<ScopeInfo> scope_info)
: Scope(zone, CLASS_SCOPE, scope_info), : Scope(zone, CLASS_SCOPE, scope_info),
rare_data_and_is_parsing_heritage_(nullptr) { rare_data_and_is_parsing_heritage_(nullptr) {
...@@ -161,6 +163,25 @@ ClassScope::ClassScope(Zone* zone, AstValueFactory* ast_value_factory, ...@@ -161,6 +163,25 @@ ClassScope::ClassScope(Zone* zone, AstValueFactory* ast_value_factory,
DCHECK_NOT_NULL(brand); DCHECK_NOT_NULL(brand);
EnsureRareData()->brand = brand; EnsureRareData()->brand = brand;
} }
// If the class variable is context-allocated and its index is
// saved for deserialization, deserialize it.
if (scope_info->HasSavedClassVariableIndex()) {
int index = scope_info->SavedClassVariableContextLocalIndex();
DCHECK_GE(index, 0);
DCHECK_LT(index, scope_info->ContextLocalCount());
String name = scope_info->ContextLocalName(index);
DCHECK_EQ(scope_info->ContextLocalMode(index), VariableMode::kConst);
DCHECK_EQ(scope_info->ContextLocalInitFlag(index),
InitializationFlag::kNeedsInitialization);
DCHECK_EQ(scope_info->ContextLocalMaybeAssignedFlag(index),
MaybeAssignedFlag::kMaybeAssigned);
Variable* var = DeclareClassVariable(
ast_value_factory, ast_value_factory->GetString(handle(name, isolate)),
kNoSourcePosition);
var->AllocateTo(VariableLocation::CONTEXT,
Context::MIN_CONTEXT_SLOTS + index);
}
} }
Scope::Scope(Zone* zone, ScopeType scope_type, Handle<ScopeInfo> scope_info) Scope::Scope(Zone* zone, ScopeType scope_type, Handle<ScopeInfo> scope_info)
...@@ -358,8 +379,8 @@ Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone, ...@@ -358,8 +379,8 @@ Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone,
outer_scope = new (zone) outer_scope = new (zone)
DeclarationScope(zone, EVAL_SCOPE, handle(scope_info, isolate)); DeclarationScope(zone, EVAL_SCOPE, handle(scope_info, isolate));
} else if (scope_info.scope_type() == CLASS_SCOPE) { } else if (scope_info.scope_type() == CLASS_SCOPE) {
outer_scope = new (zone) outer_scope = new (zone) ClassScope(isolate, zone, ast_value_factory,
ClassScope(zone, ast_value_factory, handle(scope_info, isolate)); handle(scope_info, isolate));
} else if (scope_info.scope_type() == BLOCK_SCOPE) { } else if (scope_info.scope_type() == BLOCK_SCOPE) {
if (scope_info.is_declaration_scope()) { if (scope_info.is_declaration_scope()) {
outer_scope = new (zone) outer_scope = new (zone)
...@@ -561,7 +582,8 @@ bool DeclarationScope::Analyze(ParseInfo* info) { ...@@ -561,7 +582,8 @@ bool DeclarationScope::Analyze(ParseInfo* info) {
if (scope->must_use_preparsed_scope_data_) { if (scope->must_use_preparsed_scope_data_) {
DCHECK_EQ(scope->scope_type_, ScopeType::FUNCTION_SCOPE); DCHECK_EQ(scope->scope_type_, ScopeType::FUNCTION_SCOPE);
allow_deref.emplace(); allow_deref.emplace();
info->consumed_preparse_data()->RestoreScopeAllocationData(scope); info->consumed_preparse_data()->RestoreScopeAllocationData(
scope, info->ast_value_factory());
} }
if (!scope->AllocateVariables(info)) return false; if (!scope->AllocateVariables(info)) return false;
...@@ -1750,6 +1772,15 @@ void Scope::Print(int n) { ...@@ -1750,6 +1772,15 @@ void Scope::Print(int n) {
PrintVar(n1, brand); PrintVar(n1, brand);
} }
} }
if (class_scope->class_variable() != nullptr) {
Indent(n1, "// class var");
PrintF("%s%s:\n",
class_scope->class_variable()->is_used() ? ", used" : ", unused",
class_scope->should_save_class_variable_index()
? ", index saved"
: ", index not saved");
PrintVar(n1, class_scope->class_variable());
}
} }
// Print inner scopes (disable by providing negative n). // Print inner scopes (disable by providing negative n).
...@@ -2115,8 +2146,7 @@ bool Scope::MustAllocateInContext(Variable* var) { ...@@ -2115,8 +2146,7 @@ bool Scope::MustAllocateInContext(Variable* var) {
if (mode == VariableMode::kTemporary) return false; if (mode == VariableMode::kTemporary) return false;
if (is_catch_scope()) return true; if (is_catch_scope()) return true;
if (is_script_scope() || is_eval_scope()) { if (is_script_scope() || is_eval_scope()) {
if (IsLexicalVariableMode(mode) || if (IsLexicalVariableMode(mode)) {
IsPrivateMethodOrAccessorVariableMode(mode)) {
return true; return true;
} }
} }
...@@ -2424,6 +2454,9 @@ Variable* ClassScope::DeclarePrivateName(const AstRawString* name, ...@@ -2424,6 +2454,9 @@ Variable* ClassScope::DeclarePrivateName(const AstRawString* name,
MaybeAssignedFlag::kMaybeAssigned, is_static_flag, was_added); MaybeAssignedFlag::kMaybeAssigned, is_static_flag, was_added);
if (*was_added) { if (*was_added) {
locals_.Add(result); locals_.Add(result);
has_static_private_methods_ |=
(result->is_static() &&
IsPrivateMethodOrAccessorVariableMode(result->mode()));
} else if (IsComplementaryAccessorPair(result->mode(), mode) && } else if (IsComplementaryAccessorPair(result->mode(), mode) &&
result->is_static_flag() == is_static_flag) { result->is_static_flag() == is_static_flag) {
*was_added = true; *was_added = true;
...@@ -2554,13 +2587,15 @@ bool ClassScope::ResolvePrivateNames(ParseInfo* info) { ...@@ -2554,13 +2587,15 @@ bool ClassScope::ResolvePrivateNames(ParseInfo* info) {
for (VariableProxy* proxy : list) { for (VariableProxy* proxy : list) {
Variable* var = LookupPrivateName(proxy); Variable* var = LookupPrivateName(proxy);
if (var == nullptr) { if (var == nullptr) {
// It's only possible to fail to resolve private names here if
// this is at the top level or the private name is accessed through eval.
DCHECK(info->is_eval() || outer_scope_->is_script_scope());
Scanner::Location loc = proxy->location(); Scanner::Location loc = proxy->location();
info->pending_error_handler()->ReportMessageAt( info->pending_error_handler()->ReportMessageAt(
loc.beg_pos, loc.end_pos, loc.beg_pos, loc.end_pos,
MessageTemplate::kInvalidPrivateFieldResolution, proxy->raw_name()); MessageTemplate::kInvalidPrivateFieldResolution, proxy->raw_name());
return false; return false;
} else { } else {
var->set_is_used();
proxy->BindTo(var); proxy->BindTo(var);
} }
} }
...@@ -2603,6 +2638,12 @@ VariableProxy* ClassScope::ResolvePrivateNamesPartially() { ...@@ -2603,6 +2638,12 @@ VariableProxy* ClassScope::ResolvePrivateNamesPartially() {
if (var != nullptr) { if (var != nullptr) {
var->set_is_used(); var->set_is_used();
proxy->BindTo(var); proxy->BindTo(var);
// If the variable being accessed is a static private method, we need to
// save the class variable in the context to check that the receiver is
// the class during runtime.
has_explicit_static_private_methods_access_ |=
(var->is_static() &&
IsPrivateMethodOrAccessorVariableMode(var->mode()));
} }
} }
...@@ -2645,6 +2686,21 @@ Variable* ClassScope::DeclareBrandVariable(AstValueFactory* ast_value_factory, ...@@ -2645,6 +2686,21 @@ Variable* ClassScope::DeclareBrandVariable(AstValueFactory* ast_value_factory,
return brand; return brand;
} }
Variable* ClassScope::DeclareClassVariable(AstValueFactory* ast_value_factory,
const AstRawString* name,
int class_token_pos) {
DCHECK_NULL(class_variable_);
bool was_added;
class_variable_ =
Declare(zone(), name == nullptr ? ast_value_factory->dot_string() : name,
VariableMode::kConst, NORMAL_VARIABLE,
InitializationFlag::kNeedsInitialization,
MaybeAssignedFlag::kMaybeAssigned, &was_added);
DCHECK(was_added);
class_variable_->set_initializer_position(class_token_pos);
return class_variable_;
}
PrivateNameScopeIterator::PrivateNameScopeIterator(Scope* start) PrivateNameScopeIterator::PrivateNameScopeIterator(Scope* start)
: start_scope_(start), current_scope_(start) { : start_scope_(start), current_scope_(start) {
if (!start->is_class_scope() || start->AsClassScope()->IsParsingHeritage()) { if (!start->is_class_scope() || start->AsClassScope()->IsParsingHeritage()) {
......
...@@ -1246,9 +1246,9 @@ class ModuleScope final : public DeclarationScope { ...@@ -1246,9 +1246,9 @@ class ModuleScope final : public DeclarationScope {
class V8_EXPORT_PRIVATE ClassScope : public Scope { class V8_EXPORT_PRIVATE ClassScope : public Scope {
public: public:
ClassScope(Zone* zone, Scope* outer_scope); ClassScope(Zone* zone, Scope* outer_scope, bool is_anonymous);
// Deserialization. // Deserialization.
ClassScope(Zone* zone, AstValueFactory* ast_value_factory, ClassScope(Isolate* isolate, Zone* zone, AstValueFactory* ast_value_factory,
Handle<ScopeInfo> scope_info); Handle<ScopeInfo> scope_info);
struct HeritageParsingScope { struct HeritageParsingScope {
...@@ -1298,14 +1298,47 @@ class V8_EXPORT_PRIVATE ClassScope : public Scope { ...@@ -1298,14 +1298,47 @@ class V8_EXPORT_PRIVATE ClassScope : public Scope {
Variable* DeclareBrandVariable(AstValueFactory* ast_value_factory, Variable* DeclareBrandVariable(AstValueFactory* ast_value_factory,
IsStaticFlag is_static_flag, IsStaticFlag is_static_flag,
int class_token_pos); int class_token_pos);
Variable* DeclareClassVariable(AstValueFactory* ast_value_factory,
const AstRawString* name, int class_token_pos);
Variable* brand() { Variable* brand() {
return GetRareData() == nullptr ? nullptr : GetRareData()->brand; return GetRareData() == nullptr ? nullptr : GetRareData()->brand;
} }
Variable* class_variable() { return class_variable_; }
V8_INLINE bool IsParsingHeritage() { V8_INLINE bool IsParsingHeritage() {
return rare_data_and_is_parsing_heritage_.GetPayload(); return rare_data_and_is_parsing_heritage_.GetPayload();
} }
// Only maintained when the scope is parsed, not when the scope is
// deserialized.
bool has_static_private_methods() const {
return has_static_private_methods_;
}
// Returns whether the index of class variable of this class scope should be
// recorded in the ScopeInfo.
// If any inner scope accesses static private names directly, the class
// variable will be forced to be context-allocated.
// The inner scope may also calls eval which may results in access to
// static private names.
// Only maintained when the scope is parsed.
bool should_save_class_variable_index() const {
return should_save_class_variable_index_ ||
has_explicit_static_private_methods_access_ ||
(has_static_private_methods_ && inner_scope_calls_eval_);
}
// Only maintained when the scope is parsed.
bool is_anonymous_class() const { return is_anonymous_class_; }
// Overriden during reparsing
void set_should_save_class_variable_index() {
should_save_class_variable_index_ = true;
}
private: private:
friend class Scope; friend class Scope;
friend class PrivateNameScopeIterator; friend class PrivateNameScopeIterator;
...@@ -1342,6 +1375,15 @@ class V8_EXPORT_PRIVATE ClassScope : public Scope { ...@@ -1342,6 +1375,15 @@ class V8_EXPORT_PRIVATE ClassScope : public Scope {
} }
PointerWithPayload<RareData, bool, 1> rare_data_and_is_parsing_heritage_; PointerWithPayload<RareData, bool, 1> rare_data_and_is_parsing_heritage_;
Variable* class_variable_ = nullptr;
// These are only maintained when the scope is parsed, not when the
// scope is deserialized.
bool has_static_private_methods_ = false;
bool has_explicit_static_private_methods_access_ = false;
bool is_anonymous_class_ = false;
// This is only maintained during reparsing, restored from the
// preparsed data.
bool should_save_class_variable_index_ = false;
}; };
// Iterate over the private name scope chain. The iteration proceeds from the // Iterate over the private name scope chain. The iteration proceeds from the
......
...@@ -2285,6 +2285,7 @@ void ScopeInfo::ScopeInfoPrint(std::ostream& os) { // NOLINT ...@@ -2285,6 +2285,7 @@ void ScopeInfo::ScopeInfoPrint(std::ostream& os) { // NOLINT
os << "\n - receiver: " << ReceiverVariableField::decode(flags); os << "\n - receiver: " << ReceiverVariableField::decode(flags);
} }
if (HasClassBrand()) os << "\n - has class brand"; if (HasClassBrand()) os << "\n - has class brand";
if (HasSavedClassVariableIndex()) os << "\n - has saved class variable index";
if (HasNewTarget()) os << "\n - needs new target"; if (HasNewTarget()) os << "\n - needs new target";
if (HasFunctionName()) { if (HasFunctionName()) {
os << "\n - function name(" << FunctionVariableField::decode(flags) os << "\n - function name(" << FunctionVariableField::decode(flags)
......
...@@ -2160,22 +2160,22 @@ void BytecodeGenerator::BuildClassLiteral(ClassLiteral* expr, Register name) { ...@@ -2160,22 +2160,22 @@ void BytecodeGenerator::BuildClassLiteral(ClassLiteral* expr, Register name) {
builder()->StoreAccumulatorInRegister(prototype); builder()->StoreAccumulatorInRegister(prototype);
// Assign to class variable. // Assign to class variable.
if (expr->class_variable() != nullptr) { Variable* class_variable = expr->scope()->class_variable();
DCHECK(expr->class_variable()->IsStackLocal() || if (class_variable != nullptr && class_variable->is_used()) {
expr->class_variable()->IsContextSlot()); DCHECK(class_variable->IsStackLocal() || class_variable->IsContextSlot());
builder()->LoadAccumulatorWithRegister(class_constructor); builder()->LoadAccumulatorWithRegister(class_constructor);
BuildVariableAssignment(expr->class_variable(), Token::INIT, BuildVariableAssignment(class_variable, Token::INIT,
HoleCheckMode::kElided); HoleCheckMode::kElided);
} }
// Create the class brand symbol and store it on the context // Create the class brand symbol and store it on the context
// during class evaluation. This will be stored in the // during class evaluation. The instance brand will be stored in the
// receiver later in the constructor. // instance later in the constructor.
if (expr->scope()->brand() != nullptr) { if (expr->scope()->brand() != nullptr) {
Register brand = register_allocator()->NewRegister(); Register brand = register_allocator()->NewRegister();
const AstRawString* class_name = const AstRawString* class_name =
expr->class_variable() != nullptr expr->scope()->class_variable() != nullptr
? expr->class_variable()->raw_name() ? expr->scope()->class_variable()->raw_name()
: ast_string_constants()->empty_string(); : ast_string_constants()->empty_string();
builder() builder()
->LoadLiteral(class_name) ->LoadLiteral(class_name)
...@@ -2183,37 +2183,41 @@ void BytecodeGenerator::BuildClassLiteral(ClassLiteral* expr, Register name) { ...@@ -2183,37 +2183,41 @@ void BytecodeGenerator::BuildClassLiteral(ClassLiteral* expr, Register name) {
.CallRuntime(Runtime::kCreatePrivateNameSymbol, brand); .CallRuntime(Runtime::kCreatePrivateNameSymbol, brand);
BuildVariableAssignment(expr->scope()->brand(), Token::INIT, BuildVariableAssignment(expr->scope()->brand(), Token::INIT,
HoleCheckMode::kElided); HoleCheckMode::kElided);
}
// Store the home object for any private methods that need // Store the home object for any private methods that need
// them. We do this here once the prototype and brand symbol has // them. We do this here once the prototype and brand symbol has
// been created. Private accessors have their home object set later // been created. Private accessors have their home object set later
// when they are defined. // when they are defined.
for (int i = 0; i < expr->properties()->length(); i++) { for (int i = 0; i < expr->properties()->length(); i++) {
ClassLiteral::Property* property = expr->properties()->at(i);
if (property->NeedsHomeObjectOnClassPrototype()) {
RegisterAllocationScope register_scope(this); RegisterAllocationScope register_scope(this);
ClassLiteral::Property* property = expr->properties()->at(i); Register home_object =
if (property->NeedsHomeObjectOnClassPrototype()) { property->is_static() ? class_constructor : prototype;
Register func = register_allocator()->NewRegister(); Register func = register_allocator()->NewRegister();
BuildVariableLoad(property->private_name_var(), HoleCheckMode::kElided); BuildVariableLoad(property->private_name_var(), HoleCheckMode::kElided);
builder()->StoreAccumulatorInRegister(func); builder()->StoreAccumulatorInRegister(func);
VisitSetHomeObject(func, prototype, property); VisitSetHomeObject(func, home_object, property);
}
} }
}
// Define accessors, using only a single call to the runtime for each pair // Define accessors, using only a single call to the runtime for each pair
// of corresponding getters and setters. // of corresponding getters and setters.
for (auto accessors : private_accessors.ordered_accessors()) { for (auto accessors : private_accessors.ordered_accessors()) {
RegisterAllocationScope inner_register_scope(this); RegisterAllocationScope inner_register_scope(this);
RegisterList accessors_reg = register_allocator()->NewRegisterList(2); RegisterList accessors_reg = register_allocator()->NewRegisterList(2);
ClassLiteral::Property* getter = accessors.second->getter; ClassLiteral::Property* getter = accessors.second->getter;
ClassLiteral::Property* setter = accessors.second->setter; ClassLiteral::Property* setter = accessors.second->setter;
VisitLiteralAccessor(prototype, getter, accessors_reg[0]); bool is_static =
VisitLiteralAccessor(prototype, setter, accessors_reg[1]); getter != nullptr ? getter->is_static() : setter->is_static();
builder()->CallRuntime(Runtime::kCreatePrivateAccessors, accessors_reg); Register home_object = is_static ? class_constructor : prototype;
Variable* var = getter != nullptr ? getter->private_name_var() VisitLiteralAccessor(home_object, getter, accessors_reg[0]);
: setter->private_name_var(); VisitLiteralAccessor(home_object, setter, accessors_reg[1]);
DCHECK_NOT_NULL(var); builder()->CallRuntime(Runtime::kCreatePrivateAccessors, accessors_reg);
BuildVariableAssignment(var, Token::INIT, HoleCheckMode::kElided); Variable* var = getter != nullptr ? getter->private_name_var()
} : setter->private_name_var();
DCHECK_NOT_NULL(var);
BuildVariableAssignment(var, Token::INIT, HoleCheckMode::kElided);
} }
if (expr->instance_members_initializer_function() != nullptr) { if (expr->instance_members_initializer_function() != nullptr) {
...@@ -3922,7 +3926,8 @@ void BytecodeGenerator::BuildAssignment( ...@@ -3922,7 +3926,8 @@ void BytecodeGenerator::BuildAssignment(
Property* property = lhs_data.expr()->AsProperty(); Property* property = lhs_data.expr()->AsProperty();
Register object = VisitForRegisterValue(property->obj()); Register object = VisitForRegisterValue(property->obj());
Register key = VisitForRegisterValue(property->key()); Register key = VisitForRegisterValue(property->key());
BuildPrivateBrandCheck(property, object); BuildPrivateBrandCheck(property, object,
MessageTemplate::kInvalidPrivateMemberWrite);
BuildPrivateSetterAccess(object, key, value); BuildPrivateSetterAccess(object, key, value);
if (!execution_result()->IsEffect()) { if (!execution_result()->IsEffect()) {
builder()->LoadAccumulatorWithRegister(value); builder()->LoadAccumulatorWithRegister(value);
...@@ -4455,12 +4460,14 @@ void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* property) { ...@@ -4455,12 +4460,14 @@ void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* property) {
case PRIVATE_GETTER_ONLY: case PRIVATE_GETTER_ONLY:
case PRIVATE_GETTER_AND_SETTER: { case PRIVATE_GETTER_AND_SETTER: {
Register key = VisitForRegisterValue(property->key()); Register key = VisitForRegisterValue(property->key());
BuildPrivateBrandCheck(property, obj); BuildPrivateBrandCheck(property, obj,
MessageTemplate::kInvalidPrivateMemberRead);
BuildPrivateGetterAccess(obj, key); BuildPrivateGetterAccess(obj, key);
break; break;
} }
case PRIVATE_METHOD: { case PRIVATE_METHOD: {
BuildPrivateBrandCheck(property, obj); BuildPrivateBrandCheck(property, obj,
MessageTemplate::kInvalidPrivateMemberRead);
// In the case of private methods, property->key() is the function to be // In the case of private methods, property->key() is the function to be
// loaded (stored in a context slot), so load this directly. // loaded (stored in a context slot), so load this directly.
VisitForAccumulatorValue(property->key()); VisitForAccumulatorValue(property->key());
...@@ -4500,15 +4507,29 @@ void BytecodeGenerator::BuildPrivateSetterAccess(Register object, ...@@ -4500,15 +4507,29 @@ void BytecodeGenerator::BuildPrivateSetterAccess(Register object,
} }
void BytecodeGenerator::BuildPrivateBrandCheck(Property* property, void BytecodeGenerator::BuildPrivateBrandCheck(Property* property,
Register object) { Register object,
MessageTemplate tmpl) {
Variable* private_name = property->key()->AsVariableProxy()->var(); Variable* private_name = property->key()->AsVariableProxy()->var();
DCHECK(private_name->requires_brand_check()); DCHECK(IsPrivateMethodOrAccessorVariableMode(private_name->mode()));
ClassScope* scope = private_name->scope()->AsClassScope(); ClassScope* scope = private_name->scope()->AsClassScope();
Variable* brand = scope->brand(); if (private_name->is_static()) {
BuildVariableLoadForAccumulatorValue(brand, HoleCheckMode::kElided); DCHECK_NOT_NULL(scope->class_variable());
builder()->SetExpressionPosition(property); // For static private methods, the only valid receiver is the class.
builder()->LoadKeyedProperty( // Load the class constructor.
object, feedback_index(feedback_spec()->AddKeyedLoadICSlot())); BuildVariableLoadForAccumulatorValue(scope->class_variable(),
HoleCheckMode::kElided);
BytecodeLabel return_check;
builder()->CompareReference(object).JumpIfTrue(
ToBooleanMode::kAlreadyBoolean, &return_check);
BuildInvalidPropertyAccess(tmpl, property);
builder()->Bind(&return_check);
} else {
BuildVariableLoadForAccumulatorValue(scope->brand(),
HoleCheckMode::kElided);
builder()->SetExpressionPosition(property);
builder()->LoadKeyedProperty(
object, feedback_index(feedback_spec()->AddKeyedLoadICSlot()));
}
} }
void BytecodeGenerator::VisitPropertyLoadForRegister(Register obj, void BytecodeGenerator::VisitPropertyLoadForRegister(Register obj,
...@@ -5114,7 +5135,8 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -5114,7 +5135,8 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
case PRIVATE_GETTER_AND_SETTER: { case PRIVATE_GETTER_AND_SETTER: {
object = VisitForRegisterValue(property->obj()); object = VisitForRegisterValue(property->obj());
key = VisitForRegisterValue(property->key()); key = VisitForRegisterValue(property->key());
BuildPrivateBrandCheck(property, object); BuildPrivateBrandCheck(property, object,
MessageTemplate::kInvalidPrivateMemberRead);
BuildPrivateGetterAccess(object, key); BuildPrivateGetterAccess(object, key);
break; break;
} }
......
...@@ -301,10 +301,13 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> { ...@@ -301,10 +301,13 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
void VisitRestArgumentsArray(Variable* rest); void VisitRestArgumentsArray(Variable* rest);
void VisitCallSuper(Call* call); void VisitCallSuper(Call* call);
void BuildInvalidPropertyAccess(MessageTemplate tmpl, Property* property); void BuildInvalidPropertyAccess(MessageTemplate tmpl, Property* property);
void BuildPrivateBrandCheck(Property* property, Register object); void BuildPrivateBrandCheck(Property* property, Register object,
MessageTemplate tmpl);
void BuildPrivateGetterAccess(Register obj, Register access_pair); void BuildPrivateGetterAccess(Register obj, Register access_pair);
void BuildPrivateSetterAccess(Register obj, Register access_pair, void BuildPrivateSetterAccess(Register obj, Register access_pair,
Register value); Register value);
void BuildPrivateMethods(ClassLiteral* expr, bool is_static,
Register home_object);
void BuildClassLiteral(ClassLiteral* expr, Register name); void BuildClassLiteral(ClassLiteral* expr, Register name);
void VisitClassLiteral(ClassLiteral* expr, Register name); void VisitClassLiteral(ClassLiteral* expr, Register name);
void VisitNewTargetVariable(Variable* variable); void VisitNewTargetVariable(Variable* variable);
......
...@@ -138,6 +138,10 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope, ...@@ -138,6 +138,10 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
const bool has_brand = scope->is_class_scope() const bool has_brand = scope->is_class_scope()
? scope->AsClassScope()->brand() != nullptr ? scope->AsClassScope()->brand() != nullptr
: false; : false;
const bool should_save_class_variable_index =
scope->is_class_scope()
? scope->AsClassScope()->should_save_class_variable_index()
: false;
const bool has_function_name = function_name_info != NONE; const bool has_function_name = function_name_info != NONE;
const bool has_position_info = NeedsPositionInfo(scope->scope_type()); const bool has_position_info = NeedsPositionInfo(scope->scope_type());
const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT; const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT;
...@@ -148,6 +152,7 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope, ...@@ -148,6 +152,7 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
const bool has_outer_scope_info = !outer_scope.is_null(); const bool has_outer_scope_info = !outer_scope.is_null();
const int length = kVariablePartIndex + 2 * context_local_count + const int length = kVariablePartIndex + 2 * context_local_count +
(should_save_class_variable_index ? 1 : 0) +
(has_receiver ? 1 : 0) + (has_receiver ? 1 : 0) +
(has_function_name ? kFunctionNameEntries : 0) + (has_function_name ? kFunctionNameEntries : 0) +
(has_inferred_function_name ? 1 : 0) + (has_inferred_function_name ? 1 : 0) +
...@@ -191,6 +196,8 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope, ...@@ -191,6 +196,8 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
DeclarationScopeField::encode(scope->is_declaration_scope()) | DeclarationScopeField::encode(scope->is_declaration_scope()) |
ReceiverVariableField::encode(receiver_info) | ReceiverVariableField::encode(receiver_info) |
HasClassBrandField::encode(has_brand) | HasClassBrandField::encode(has_brand) |
HasSavedClassVariableIndexField::encode(
should_save_class_variable_index) |
HasNewTargetField::encode(has_new_target) | HasNewTargetField::encode(has_new_target) |
FunctionVariableField::encode(function_name_info) | FunctionVariableField::encode(function_name_info) |
HasInferredFunctionNameField::encode(has_inferred_function_name) | HasInferredFunctionNameField::encode(has_inferred_function_name) |
...@@ -293,6 +300,16 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope, ...@@ -293,6 +300,16 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
index += 2 * context_local_count; index += 2 * context_local_count;
DCHECK_EQ(index, scope_info.SavedClassVariableInfoIndex());
// If the scope is a class scope and has used static private methods, save
// the context slot index of the class variable.
// Store the class variable index.
if (should_save_class_variable_index) {
Variable* class_variable = scope->AsClassScope()->class_variable();
DCHECK_EQ(class_variable->location(), VariableLocation::CONTEXT);
scope_info.set(index++, Smi::FromInt(class_variable->index()));
}
// If the receiver is allocated, add its index. // If the receiver is allocated, add its index.
DCHECK_EQ(index, scope_info.ReceiverInfoIndex()); DCHECK_EQ(index, scope_info.ReceiverInfoIndex());
if (has_receiver) { if (has_receiver) {
...@@ -372,6 +389,7 @@ Handle<ScopeInfo> ScopeInfo::CreateForWithScope( ...@@ -372,6 +389,7 @@ Handle<ScopeInfo> ScopeInfo::CreateForWithScope(
LanguageModeField::encode(LanguageMode::kSloppy) | LanguageModeField::encode(LanguageMode::kSloppy) |
DeclarationScopeField::encode(false) | DeclarationScopeField::encode(false) |
ReceiverVariableField::encode(NONE) | HasClassBrandField::encode(false) | ReceiverVariableField::encode(NONE) | HasClassBrandField::encode(false) |
HasSavedClassVariableIndexField::encode(false) |
HasNewTargetField::encode(false) | FunctionVariableField::encode(NONE) | HasNewTargetField::encode(false) | FunctionVariableField::encode(NONE) |
IsAsmModuleField::encode(false) | HasSimpleParametersField::encode(true) | IsAsmModuleField::encode(false) | HasSimpleParametersField::encode(true) |
FunctionKindField::encode(kNormalFunction) | FunctionKindField::encode(kNormalFunction) |
...@@ -438,7 +456,9 @@ Handle<ScopeInfo> ScopeInfo::CreateForBootstrapping(Isolate* isolate, ...@@ -438,7 +456,9 @@ Handle<ScopeInfo> ScopeInfo::CreateForBootstrapping(Isolate* isolate,
LanguageModeField::encode(LanguageMode::kSloppy) | LanguageModeField::encode(LanguageMode::kSloppy) |
DeclarationScopeField::encode(true) | DeclarationScopeField::encode(true) |
ReceiverVariableField::encode(is_empty_function ? UNUSED : CONTEXT) | ReceiverVariableField::encode(is_empty_function ? UNUSED : CONTEXT) |
HasClassBrandField::encode(false) | HasNewTargetField::encode(false) | HasClassBrandField::encode(false) |
HasSavedClassVariableIndexField::encode(false) |
HasNewTargetField::encode(false) |
FunctionVariableField::encode(is_empty_function ? UNUSED : NONE) | FunctionVariableField::encode(is_empty_function ? UNUSED : NONE) |
HasInferredFunctionNameField::encode(has_inferred_function_name) | HasInferredFunctionNameField::encode(has_inferred_function_name) |
IsAsmModuleField::encode(false) | HasSimpleParametersField::encode(true) | IsAsmModuleField::encode(false) | HasSimpleParametersField::encode(true) |
...@@ -566,6 +586,10 @@ bool ScopeInfo::HasClassBrand() const { ...@@ -566,6 +586,10 @@ bool ScopeInfo::HasClassBrand() const {
return HasClassBrandField::decode(Flags()); return HasClassBrandField::decode(Flags());
} }
bool ScopeInfo::HasSavedClassVariableIndex() const {
return HasSavedClassVariableIndexField::decode(Flags());
}
bool ScopeInfo::HasNewTarget() const { bool ScopeInfo::HasNewTarget() const {
return HasNewTargetField::decode(Flags()); return HasNewTargetField::decode(Flags());
} }
...@@ -807,6 +831,14 @@ int ScopeInfo::ContextSlotIndex(ScopeInfo scope_info, String name, ...@@ -807,6 +831,14 @@ int ScopeInfo::ContextSlotIndex(ScopeInfo scope_info, String name,
return -1; return -1;
} }
int ScopeInfo::SavedClassVariableContextLocalIndex() const {
if (length() > 0 && HasSavedClassVariableIndexField::decode(Flags())) {
int index = Smi::ToInt(get(SavedClassVariableInfoIndex()));
return index - Context::MIN_CONTEXT_SLOTS;
}
return -1;
}
int ScopeInfo::ReceiverContextSlotIndex() const { int ScopeInfo::ReceiverContextSlotIndex() const {
if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT) { if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT) {
return Smi::ToInt(get(ReceiverInfoIndex())); return Smi::ToInt(get(ReceiverInfoIndex()));
...@@ -838,10 +870,14 @@ int ScopeInfo::ContextLocalInfosIndex() const { ...@@ -838,10 +870,14 @@ int ScopeInfo::ContextLocalInfosIndex() const {
return ContextLocalNamesIndex() + ContextLocalCount(); return ContextLocalNamesIndex() + ContextLocalCount();
} }
int ScopeInfo::ReceiverInfoIndex() const { int ScopeInfo::SavedClassVariableInfoIndex() const {
return ContextLocalInfosIndex() + ContextLocalCount(); return ContextLocalInfosIndex() + ContextLocalCount();
} }
int ScopeInfo::ReceiverInfoIndex() const {
return SavedClassVariableInfoIndex() + (HasSavedClassVariableIndex() ? 1 : 0);
}
int ScopeInfo::FunctionNameInfoIndex() const { int ScopeInfo::FunctionNameInfoIndex() const {
return ReceiverInfoIndex() + (HasAllocatedReceiver() ? 1 : 0); return ReceiverInfoIndex() + (HasAllocatedReceiver() ? 1 : 0);
} }
......
...@@ -75,6 +75,10 @@ class ScopeInfo : public FixedArray { ...@@ -75,6 +75,10 @@ class ScopeInfo : public FixedArray {
// Does this scope has class brand (for private methods)? // Does this scope has class brand (for private methods)?
bool HasClassBrand() const; bool HasClassBrand() const;
// Does this scope contains a saved class variable context local slot index
// for checking receivers of static private methods?
bool HasSavedClassVariableIndex() const;
// Does this scope declare a "new.target" binding? // Does this scope declare a "new.target" binding?
bool HasNewTarget() const; bool HasNewTarget() const;
...@@ -168,6 +172,12 @@ class ScopeInfo : public FixedArray { ...@@ -168,6 +172,12 @@ class ScopeInfo : public FixedArray {
// context-allocated. Otherwise returns a value < 0. // context-allocated. Otherwise returns a value < 0.
int ReceiverContextSlotIndex() const; int ReceiverContextSlotIndex() const;
// Lookup support for serialized scope info. Returns the index of the
// saved class variable in context local slots if scope is a class scope
// and it contains static private methods that may be accessed.
// Otherwise returns a value < 0.
int SavedClassVariableContextLocalIndex() const;
FunctionKind function_kind() const; FunctionKind function_kind() const;
// Returns true if this ScopeInfo is linked to a outer ScopeInfo. // Returns true if this ScopeInfo is linked to a outer ScopeInfo.
...@@ -239,7 +249,8 @@ class ScopeInfo : public FixedArray { ...@@ -239,7 +249,8 @@ class ScopeInfo : public FixedArray {
using ReceiverVariableField = using ReceiverVariableField =
DeclarationScopeField::Next<VariableAllocationInfo, 2>; DeclarationScopeField::Next<VariableAllocationInfo, 2>;
using HasClassBrandField = ReceiverVariableField::Next<bool, 1>; using HasClassBrandField = ReceiverVariableField::Next<bool, 1>;
using HasNewTargetField = HasClassBrandField::Next<bool, 1>; using HasSavedClassVariableIndexField = HasClassBrandField::Next<bool, 1>;
using HasNewTargetField = HasSavedClassVariableIndexField::Next<bool, 1>;
using FunctionVariableField = using FunctionVariableField =
HasNewTargetField::Next<VariableAllocationInfo, 2>; HasNewTargetField::Next<VariableAllocationInfo, 2>;
// TODO(cbruni): Combine with function variable field when only storing the // TODO(cbruni): Combine with function variable field when only storing the
...@@ -271,27 +282,32 @@ class ScopeInfo : public FixedArray { ...@@ -271,27 +282,32 @@ class ScopeInfo : public FixedArray {
// the context locals in ContextLocalNames. One slot is used per // the context locals in ContextLocalNames. One slot is used per
// context local, so in total this part occupies ContextLocalCount() // context local, so in total this part occupies ContextLocalCount()
// slots in the array. // slots in the array.
// 3. ReceiverInfo: // 3. SavedClassVariableInfo:
// If the scope is a class scope and it has static private methods that
// may be accessed directly or through eval, one slot is reserved to hold
// the context slot index for the class variable.
// 4. ReceiverInfo:
// If the scope binds a "this" value, one slot is reserved to hold the // If the scope binds a "this" value, one slot is reserved to hold the
// context or stack slot index for the variable. // context or stack slot index for the variable.
// 4. FunctionNameInfo: // 5. FunctionNameInfo:
// If the scope belongs to a named function expression this part contains // If the scope belongs to a named function expression this part contains
// information about the function variable. It always occupies two array // information about the function variable. It always occupies two array
// slots: a. The name of the function variable. // slots: a. The name of the function variable.
// b. The context or stack slot index for the variable. // b. The context or stack slot index for the variable.
// 5. InferredFunctionName: // 6. InferredFunctionName:
// Contains the function's inferred name. // Contains the function's inferred name.
// 6. SourcePosition: // 7. SourcePosition:
// Contains two slots with a) the startPosition and b) the endPosition if // Contains two slots with a) the startPosition and b) the endPosition if
// the scope belongs to a function or script. // the scope belongs to a function or script.
// 7. OuterScopeInfoIndex: // 8. OuterScopeInfoIndex:
// The outer scope's ScopeInfo or the hole if there's none. // The outer scope's ScopeInfo or the hole if there's none.
// 8. SourceTextModuleInfo, ModuleVariableCount, and ModuleVariables: // 9. SourceTextModuleInfo, ModuleVariableCount, and ModuleVariables:
// For a module scope, this part contains the SourceTextModuleInfo, the // For a module scope, this part contains the SourceTextModuleInfo, the
// number of MODULE-allocated variables, and the metadata of those // number of MODULE-allocated variables, and the metadata of those
// variables. For non-module scopes it is empty. // variables. For non-module scopes it is empty.
int ContextLocalNamesIndex() const; int ContextLocalNamesIndex() const;
int ContextLocalInfosIndex() const; int ContextLocalInfosIndex() const;
int SavedClassVariableInfoIndex() const;
int ReceiverInfoIndex() const; int ReceiverInfoIndex() const;
int FunctionNameInfoIndex() const; int FunctionNameInfoIndex() const;
int InferredFunctionNameIndex() const; int InferredFunctionNameIndex() const;
......
...@@ -529,8 +529,7 @@ class ParserBase { ...@@ -529,8 +529,7 @@ class ParserBase {
struct ClassInfo { struct ClassInfo {
public: public:
explicit ClassInfo(ParserBase* parser) explicit ClassInfo(ParserBase* parser)
: variable(nullptr), : extends(parser->impl()->NullExpression()),
extends(parser->impl()->NullExpression()),
properties(parser->impl()->NewClassPropertyList(4)), properties(parser->impl()->NewClassPropertyList(4)),
static_fields(parser->impl()->NewClassPropertyList(4)), static_fields(parser->impl()->NewClassPropertyList(4)),
instance_fields(parser->impl()->NewClassPropertyList(4)), instance_fields(parser->impl()->NewClassPropertyList(4)),
...@@ -545,7 +544,6 @@ class ParserBase { ...@@ -545,7 +544,6 @@ class ParserBase {
static_fields_scope(nullptr), static_fields_scope(nullptr),
instance_members_scope(nullptr), instance_members_scope(nullptr),
computed_field_count(0) {} computed_field_count(0) {}
Variable* variable;
ExpressionT extends; ExpressionT extends;
ClassPropertyListT properties; ClassPropertyListT properties;
ClassPropertyListT static_fields; ClassPropertyListT static_fields;
...@@ -672,8 +670,8 @@ class ParserBase { ...@@ -672,8 +670,8 @@ class ParserBase {
return new (zone()) DeclarationScope(zone(), parent, EVAL_SCOPE); return new (zone()) DeclarationScope(zone(), parent, EVAL_SCOPE);
} }
ClassScope* NewClassScope(Scope* parent) const { ClassScope* NewClassScope(Scope* parent, bool is_anonymous) const {
return new (zone()) ClassScope(zone(), parent); return new (zone()) ClassScope(zone(), parent, is_anonymous);
} }
Scope* NewScope(ScopeType scope_type) const { Scope* NewScope(ScopeType scope_type) const {
...@@ -4392,13 +4390,12 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral( ...@@ -4392,13 +4390,12 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
} }
} }
ClassScope* class_scope = NewClassScope(scope()); ClassScope* class_scope = NewClassScope(scope(), is_anonymous);
BlockState block_state(&scope_, class_scope); BlockState block_state(&scope_, class_scope);
RaiseLanguageMode(LanguageMode::kStrict); RaiseLanguageMode(LanguageMode::kStrict);
ClassInfo class_info(this); ClassInfo class_info(this);
class_info.is_anonymous = is_anonymous; class_info.is_anonymous = is_anonymous;
impl()->DeclareClassVariable(name, &class_info, class_token_pos);
scope()->set_start_position(end_position()); scope()->set_start_position(end_position());
if (Check(Token::EXTENDS)) { if (Check(Token::EXTENDS)) {
...@@ -4437,7 +4434,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral( ...@@ -4437,7 +4434,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
if (V8_UNLIKELY(prop_info.is_private)) { if (V8_UNLIKELY(prop_info.is_private)) {
DCHECK(!is_constructor); DCHECK(!is_constructor);
class_info.requires_brand |= !is_field; class_info.requires_brand |= (!is_field && !prop_info.is_static);
impl()->DeclarePrivateClassMember(class_scope, prop_info.name, property, impl()->DeclarePrivateClassMember(class_scope, prop_info.name, property,
property_kind, prop_info.is_static, property_kind, prop_info.is_static,
&class_info); &class_info);
...@@ -4481,6 +4478,17 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral( ...@@ -4481,6 +4478,17 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
ast_value_factory(), IsStaticFlag::kNotStatic, kNoSourcePosition); ast_value_factory(), IsStaticFlag::kNotStatic, kNoSourcePosition);
} }
bool should_save_class_variable_index =
class_scope->should_save_class_variable_index();
if (!is_anonymous || should_save_class_variable_index) {
impl()->DeclareClassVariable(class_scope, name, &class_info,
class_token_pos);
if (should_save_class_variable_index) {
class_scope->class_variable()->set_is_used();
class_scope->class_variable()->ForceContextAllocation();
}
}
return impl()->RewriteClassLiteral(class_scope, name, &class_info, return impl()->RewriteClassLiteral(class_scope, name, &class_info,
class_token_pos, end_pos); class_token_pos, end_pos);
} }
......
...@@ -2773,17 +2773,20 @@ void Parser::ParseFunction( ...@@ -2773,17 +2773,20 @@ void Parser::ParseFunction(
*suspend_count = function_state.suspend_count(); *suspend_count = function_state.suspend_count();
} }
void Parser::DeclareClassVariable(const AstRawString* name, void Parser::DeclareClassVariable(ClassScope* scope, const AstRawString* name,
ClassInfo* class_info, int class_token_pos) { ClassInfo* class_info, int class_token_pos) {
#ifdef DEBUG #ifdef DEBUG
scope()->SetScopeName(name); scope->SetScopeName(name);
#endif #endif
if (name != nullptr) { DCHECK_IMPLIES(name == nullptr, class_info->is_anonymous);
VariableProxy* proxy = // Declare a special class variable for anonymous classes with the dot
DeclareBoundVariable(name, VariableMode::kConst, class_token_pos); // if we need to save it for static private method access.
class_info->variable = proxy->var(); Variable* class_variable =
} scope->DeclareClassVariable(ast_value_factory(), name, class_token_pos);
Declaration* declaration = factory()->NewVariableDeclaration(class_token_pos);
scope->declarations()->Add(declaration);
declaration->set_var(class_variable);
} }
// TODO(gsathya): Ideally, this should just bypass scope analysis and // TODO(gsathya): Ideally, this should just bypass scope analysis and
...@@ -2932,8 +2935,8 @@ Expression* Parser::RewriteClassLiteral(ClassScope* block_scope, ...@@ -2932,8 +2935,8 @@ Expression* Parser::RewriteClassLiteral(ClassScope* block_scope,
} }
if (name != nullptr) { if (name != nullptr) {
DCHECK_NOT_NULL(class_info->variable); DCHECK_NOT_NULL(block_scope->class_variable());
class_info->variable->set_initializer_position(end_pos); block_scope->class_variable()->set_initializer_position(end_pos);
} }
FunctionLiteral* static_fields_initializer = nullptr; FunctionLiteral* static_fields_initializer = nullptr;
...@@ -2954,10 +2957,10 @@ Expression* Parser::RewriteClassLiteral(ClassScope* block_scope, ...@@ -2954,10 +2957,10 @@ Expression* Parser::RewriteClassLiteral(ClassScope* block_scope,
} }
ClassLiteral* class_literal = factory()->NewClassLiteral( ClassLiteral* class_literal = factory()->NewClassLiteral(
block_scope, class_info->variable, class_info->extends, block_scope, class_info->extends, class_info->constructor,
class_info->constructor, class_info->properties, class_info->properties, static_fields_initializer,
static_fields_initializer, instance_members_initializer_function, pos, instance_members_initializer_function, pos, end_pos,
end_pos, class_info->has_name_static_property, class_info->has_name_static_property,
class_info->has_static_computed_names, class_info->is_anonymous); class_info->has_static_computed_names, class_info->is_anonymous);
AddFunctionForNameInference(class_info->constructor); AddFunctionForNameInference(class_info->constructor);
......
...@@ -316,8 +316,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { ...@@ -316,8 +316,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
Statement* DeclareClass(const AstRawString* variable_name, Expression* value, Statement* DeclareClass(const AstRawString* variable_name, Expression* value,
ZonePtrList<const AstRawString>* names, ZonePtrList<const AstRawString>* names,
int class_token_pos, int end_pos); int class_token_pos, int end_pos);
void DeclareClassVariable(const AstRawString* name, ClassInfo* class_info, void DeclareClassVariable(ClassScope* scope, const AstRawString* name,
int class_token_pos); ClassInfo* class_info, int class_token_pos);
void DeclareClassBrandVariable(ClassScope* scope, ClassInfo* class_info, void DeclareClassBrandVariable(ClassScope* scope, ClassInfo* class_info,
int class_token_pos); int class_token_pos);
void DeclarePrivateClassMember(ClassScope* scope, void DeclarePrivateClassMember(ClassScope* scope,
......
...@@ -157,16 +157,18 @@ class BaseConsumedPreparseData : public ConsumedPreparseData { ...@@ -157,16 +157,18 @@ class BaseConsumedPreparseData : public ConsumedPreparseData {
int* function_length, int* num_inner_functions, bool* uses_super_property, int* function_length, int* num_inner_functions, bool* uses_super_property,
LanguageMode* language_mode) final; LanguageMode* language_mode) final;
void RestoreScopeAllocationData(DeclarationScope* scope) final; void RestoreScopeAllocationData(DeclarationScope* scope,
AstValueFactory* ast_value_factory) final;
#ifdef DEBUG #ifdef DEBUG
bool VerifyDataStart(); bool VerifyDataStart();
#endif #endif
private: private:
void RestoreDataForScope(Scope* scope); void RestoreDataForScope(Scope* scope, AstValueFactory* ast_value_factory);
void RestoreDataForVariable(Variable* var); void RestoreDataForVariable(Variable* var);
void RestoreDataForInnerScopes(Scope* scope); void RestoreDataForInnerScopes(Scope* scope,
AstValueFactory* ast_value_factory);
std::unique_ptr<ByteData> scope_data_; std::unique_ptr<ByteData> scope_data_;
// When consuming the data, these indexes point to the data we're going to // When consuming the data, these indexes point to the data we're going to
......
...@@ -28,6 +28,7 @@ using NeedsPrivateNameContextChainRecalcField = ...@@ -28,6 +28,7 @@ using NeedsPrivateNameContextChainRecalcField =
InnerScopeCallsEvalField::Next<bool, 1>; InnerScopeCallsEvalField::Next<bool, 1>;
using CanElideThisHoleChecks = using CanElideThisHoleChecks =
NeedsPrivateNameContextChainRecalcField::Next<bool, 1>; NeedsPrivateNameContextChainRecalcField::Next<bool, 1>;
using ShouldSaveClassVariableIndexField = CanElideThisHoleChecks::Next<bool, 1>;
using VariableMaybeAssignedField = BitField8<bool, 0, 1>; using VariableMaybeAssignedField = BitField8<bool, 0, 1>;
using VariableContextAllocatedField = VariableMaybeAssignedField::Next<bool, 1>; using VariableContextAllocatedField = VariableMaybeAssignedField::Next<bool, 1>;
...@@ -367,7 +368,10 @@ void PreparseDataBuilder::SaveDataForScope(Scope* scope) { ...@@ -367,7 +368,10 @@ void PreparseDataBuilder::SaveDataForScope(Scope* scope) {
->needs_private_name_context_chain_recalc()) | ->needs_private_name_context_chain_recalc()) |
CanElideThisHoleChecks::encode( CanElideThisHoleChecks::encode(
scope->is_declaration_scope() && scope->is_declaration_scope() &&
scope->AsDeclarationScope()->can_elide_this_hole_checks()); scope->AsDeclarationScope()->can_elide_this_hole_checks()) |
ShouldSaveClassVariableIndexField::encode(
scope->is_class_scope() &&
scope->AsClassScope()->should_save_class_variable_index());
byte_data_.Reserve(kUint8Size); byte_data_.Reserve(kUint8Size);
byte_data_.WriteUint8(scope_data_flags); byte_data_.WriteUint8(scope_data_flags);
...@@ -573,7 +577,7 @@ BaseConsumedPreparseData<Data>::GetDataForSkippableFunction( ...@@ -573,7 +577,7 @@ BaseConsumedPreparseData<Data>::GetDataForSkippableFunction(
template <class Data> template <class Data>
void BaseConsumedPreparseData<Data>::RestoreScopeAllocationData( void BaseConsumedPreparseData<Data>::RestoreScopeAllocationData(
DeclarationScope* scope) { DeclarationScope* scope, AstValueFactory* ast_value_factory) {
DCHECK_EQ(scope->scope_type(), ScopeType::FUNCTION_SCOPE); DCHECK_EQ(scope->scope_type(), ScopeType::FUNCTION_SCOPE);
typename ByteData::ReadingScope reading_scope(this); typename ByteData::ReadingScope reading_scope(this);
...@@ -588,14 +592,15 @@ void BaseConsumedPreparseData<Data>::RestoreScopeAllocationData( ...@@ -588,14 +592,15 @@ void BaseConsumedPreparseData<Data>::RestoreScopeAllocationData(
DCHECK_EQ(end_position_from_data, scope->end_position()); DCHECK_EQ(end_position_from_data, scope->end_position());
#endif #endif
RestoreDataForScope(scope); RestoreDataForScope(scope, ast_value_factory);
// Check that we consumed all scope data. // Check that we consumed all scope data.
DCHECK_EQ(scope_data_->RemainingBytes(), 0); DCHECK_EQ(scope_data_->RemainingBytes(), 0);
} }
template <typename Data> template <typename Data>
void BaseConsumedPreparseData<Data>::RestoreDataForScope(Scope* scope) { void BaseConsumedPreparseData<Data>::RestoreDataForScope(
Scope* scope, AstValueFactory* ast_value_factory) {
if (scope->is_declaration_scope() && if (scope->is_declaration_scope() &&
scope->AsDeclarationScope()->is_skipped_function()) { scope->AsDeclarationScope()->is_skipped_function()) {
return; return;
...@@ -623,17 +628,38 @@ void BaseConsumedPreparseData<Data>::RestoreDataForScope(Scope* scope) { ...@@ -623,17 +628,38 @@ void BaseConsumedPreparseData<Data>::RestoreDataForScope(Scope* scope) {
if (CanElideThisHoleChecks::decode(scope_data_flags)) { if (CanElideThisHoleChecks::decode(scope_data_flags)) {
scope->AsDeclarationScope()->set_can_elide_this_hole_checks(); scope->AsDeclarationScope()->set_can_elide_this_hole_checks();
} }
if (ShouldSaveClassVariableIndexField::decode(scope_data_flags)) {
Variable* var;
// An anonymous class whose class variable needs to be saved do not
// have the class variable created during reparse since we skip parsing
// the inner scopes that contain potential access to static private
// methods. So create it now.
if (scope->AsClassScope()->is_anonymous_class()) {
var = scope->AsClassScope()->DeclareClassVariable(
ast_value_factory, nullptr, kNoSourcePosition);
AstNodeFactory factory(ast_value_factory, ast_value_factory->zone());
Declaration* declaration =
factory.NewVariableDeclaration(kNoSourcePosition);
scope->declarations()->Add(declaration);
declaration->set_var(var);
} else {
var = scope->AsClassScope()->class_variable();
DCHECK_NOT_NULL(var);
}
var->set_is_used();
var->ForceContextAllocation();
scope->AsClassScope()->set_should_save_class_variable_index();
}
if (scope->is_function_scope()) { if (scope->is_function_scope()) {
Variable* function = scope->AsDeclarationScope()->function_var(); Variable* function = scope->AsDeclarationScope()->function_var();
if (function != nullptr) RestoreDataForVariable(function); if (function != nullptr) RestoreDataForVariable(function);
} }
for (Variable* var : *scope->locals()) { for (Variable* var : *scope->locals()) {
if (IsSerializableVariableMode(var->mode())) RestoreDataForVariable(var); if (IsSerializableVariableMode(var->mode())) RestoreDataForVariable(var);
} }
RestoreDataForInnerScopes(scope); RestoreDataForInnerScopes(scope, ast_value_factory);
} }
template <typename Data> template <typename Data>
...@@ -672,10 +698,11 @@ void BaseConsumedPreparseData<Data>::RestoreDataForVariable(Variable* var) { ...@@ -672,10 +698,11 @@ void BaseConsumedPreparseData<Data>::RestoreDataForVariable(Variable* var) {
} }
template <typename Data> template <typename Data>
void BaseConsumedPreparseData<Data>::RestoreDataForInnerScopes(Scope* scope) { void BaseConsumedPreparseData<Data>::RestoreDataForInnerScopes(
Scope* scope, AstValueFactory* ast_value_factory) {
for (Scope* inner = scope->inner_scope(); inner != nullptr; for (Scope* inner = scope->inner_scope(); inner != nullptr;
inner = inner->sibling()) { inner = inner->sibling()) {
RestoreDataForScope(inner); RestoreDataForScope(inner, ast_value_factory);
} }
} }
......
...@@ -24,6 +24,7 @@ class Parser; ...@@ -24,6 +24,7 @@ class Parser;
class PreParser; class PreParser;
class PreparseData; class PreparseData;
class ZonePreparseData; class ZonePreparseData;
class AstValueFactory;
/* /*
...@@ -288,7 +289,8 @@ class ConsumedPreparseData { ...@@ -288,7 +289,8 @@ class ConsumedPreparseData {
// Restores the information needed for allocating the Scope's (and its // Restores the information needed for allocating the Scope's (and its
// subscopes') variables. // subscopes') variables.
virtual void RestoreScopeAllocationData(DeclarationScope* scope) = 0; virtual void RestoreScopeAllocationData(
DeclarationScope* scope, AstValueFactory* ast_value_factory) = 0;
protected: protected:
ConsumedPreparseData() = default; ConsumedPreparseData() = default;
......
...@@ -1227,14 +1227,15 @@ class PreParser : public ParserBase<PreParser> { ...@@ -1227,14 +1227,15 @@ class PreParser : public ParserBase<PreParser> {
&was_added); &was_added);
return PreParserStatement::Default(); return PreParserStatement::Default();
} }
V8_INLINE void DeclareClassVariable(const PreParserIdentifier& name, V8_INLINE void DeclareClassVariable(ClassScope* scope,
const PreParserIdentifier& name,
ClassInfo* class_info, ClassInfo* class_info,
int class_token_pos) { int class_token_pos) {
if (!IsNull(name)) { DCHECK_IMPLIES(IsNull(name), class_info->is_anonymous);
bool was_added; // Declare a special class variable for anonymous classes with the dot
DeclareVariableName(name.string_, VariableMode::kConst, scope(), // if we need to save it for static private method access.
&was_added); scope->DeclareClassVariable(ast_value_factory(), name.string_,
} class_token_pos);
} }
V8_INLINE void DeclarePublicClassMethod(const PreParserIdentifier& class_name, V8_INLINE void DeclarePublicClassMethod(const PreParserIdentifier& class_name,
const PreParserExpression& property, const PreParserExpression& property,
......
...@@ -12,27 +12,26 @@ snippet: " ...@@ -12,27 +12,26 @@ snippet: "
speak() { console.log(this.name + ' is speaking.'); } speak() { console.log(this.name + ' is speaking.'); }
} }
" "
frame size: 8 frame size: 7
parameter count: 1 parameter count: 1
bytecode array length: 44 bytecode array length: 41
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
B(CreateBlockContext), U8(0), B(CreateBlockContext), U8(0),
B(PushContext), R(2), B(PushContext), R(1),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(6), B(Star), R(5),
B(CreateClosure), U8(2), U8(0), U8(2), B(CreateClosure), U8(2), U8(0), U8(2),
B(Star), R(3), B(Star), R(2),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(4), B(Star), R(3),
B(CreateClosure), U8(3), U8(1), U8(2), B(CreateClosure), U8(3), U8(1), U8(2),
B(Star), R(7), B(Star), R(6),
B(Mov), R(3), R(5), B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4), B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
B(Star), R(4), B(Star), R(3),
B(Mov), R(5), R(1), B(PopContext), R(1),
B(PopContext), R(2), B(Mov), R(4), R(0),
B(Mov), R(1), R(0),
B(LdaUndefined), B(LdaUndefined),
/* 149 S> */ B(Return), /* 149 S> */ B(Return),
] ]
...@@ -52,27 +51,26 @@ snippet: " ...@@ -52,27 +51,26 @@ snippet: "
speak() { console.log(this.name + ' is speaking.'); } speak() { console.log(this.name + ' is speaking.'); }
} }
" "
frame size: 8 frame size: 7
parameter count: 1 parameter count: 1
bytecode array length: 44 bytecode array length: 41
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
B(CreateBlockContext), U8(0), B(CreateBlockContext), U8(0),
B(PushContext), R(2), B(PushContext), R(1),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(6), B(Star), R(5),
B(CreateClosure), U8(2), U8(0), U8(2), B(CreateClosure), U8(2), U8(0), U8(2),
B(Star), R(3), B(Star), R(2),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(4), B(Star), R(3),
B(CreateClosure), U8(3), U8(1), U8(2), B(CreateClosure), U8(3), U8(1), U8(2),
B(Star), R(7), B(Star), R(6),
B(Mov), R(3), R(5), B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4), B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
B(Star), R(4), B(Star), R(3),
B(Mov), R(5), R(1), B(PopContext), R(1),
B(PopContext), R(2), B(Mov), R(4), R(0),
B(Mov), R(1), R(0),
B(LdaUndefined), B(LdaUndefined),
/* 149 S> */ B(Return), /* 149 S> */ B(Return),
] ]
...@@ -94,43 +92,42 @@ snippet: " ...@@ -94,43 +92,42 @@ snippet: "
static [n1]() { return n1; } static [n1]() { return n1; }
} }
" "
frame size: 12 frame size: 11
parameter count: 1 parameter count: 1
bytecode array length: 87 bytecode array length: 84
bytecodes: [ bytecodes: [
B(CreateFunctionContext), U8(0), U8(2), B(CreateFunctionContext), U8(0), U8(2),
B(PushContext), R(2), B(PushContext), R(1),
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
/* 43 S> */ B(LdaConstant), U8(1), /* 43 S> */ B(LdaConstant), U8(1),
/* 43 E> */ B(StaCurrentContextSlot), U8(4), /* 43 E> */ B(StaCurrentContextSlot), U8(4),
/* 57 S> */ B(LdaConstant), U8(2), /* 57 S> */ B(LdaConstant), U8(2),
/* 57 E> */ B(StaCurrentContextSlot), U8(5), /* 57 E> */ B(StaCurrentContextSlot), U8(5),
B(CreateBlockContext), U8(3), B(CreateBlockContext), U8(3),
B(PushContext), R(3), B(PushContext), R(2),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(7), B(Star), R(6),
B(CreateClosure), U8(5), U8(0), U8(2), B(CreateClosure), U8(5), U8(0), U8(2),
B(Star), R(4), B(Star), R(3),
B(LdaConstant), U8(4), B(LdaConstant), U8(4),
B(Star), R(5), B(Star), R(4),
/* 75 S> */ B(LdaImmutableContextSlot), R(3), U8(4), U8(0), /* 75 S> */ B(LdaImmutableContextSlot), R(2), U8(4), U8(0),
B(ToName), R(8), B(ToName), R(7),
B(CreateClosure), U8(6), U8(1), U8(2), B(CreateClosure), U8(6), U8(1), U8(2),
B(Star), R(9), B(Star), R(8),
/* 106 S> */ B(LdaImmutableContextSlot), R(3), U8(5), U8(0), /* 106 S> */ B(LdaImmutableContextSlot), R(2), U8(5), U8(0),
B(ToName), R(10), B(ToName), R(9),
B(LdaConstant), U8(7), B(LdaConstant), U8(7),
B(TestEqualStrict), R(10), U8(0), B(TestEqualStrict), R(9), U8(0),
B(Mov), R(4), R(6), B(Mov), R(3), R(5),
B(JumpIfFalse), U8(7), B(JumpIfFalse), U8(7),
B(CallRuntime), U16(Runtime::kThrowStaticPrototypeError), R(0), U8(0), B(CallRuntime), U16(Runtime::kThrowStaticPrototypeError), R(0), U8(0),
B(CreateClosure), U8(8), U8(2), U8(2), B(CreateClosure), U8(8), U8(2), U8(2),
B(Star), R(11), B(Star), R(10),
B(CallRuntime), U16(Runtime::kDefineClass), R(5), U8(7), B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(7),
B(Star), R(5), B(Star), R(4),
B(Mov), R(4), R(1), B(PopContext), R(2),
B(PopContext), R(3), B(Mov), R(3), R(0),
B(Mov), R(1), R(0),
B(LdaUndefined), B(LdaUndefined),
/* 129 S> */ B(Return), /* 129 S> */ B(Return),
] ]
...@@ -154,29 +151,28 @@ snippet: " ...@@ -154,29 +151,28 @@ snippet: "
class C { constructor() { count++; }} class C { constructor() { count++; }}
return new C(); return new C();
" "
frame size: 8 frame size: 7
parameter count: 1 parameter count: 1
bytecode array length: 52 bytecode array length: 49
bytecodes: [ bytecodes: [
B(CreateFunctionContext), U8(0), U8(1), B(CreateFunctionContext), U8(0), U8(1),
B(PushContext), R(2), B(PushContext), R(1),
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
/* 46 S> */ B(LdaZero), /* 46 S> */ B(LdaZero),
/* 46 E> */ B(StaCurrentContextSlot), U8(4), /* 46 E> */ B(StaCurrentContextSlot), U8(4),
B(CreateBlockContext), U8(1), B(CreateBlockContext), U8(1),
B(PushContext), R(3), B(PushContext), R(2),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(7), B(Star), R(6),
B(CreateClosure), U8(3), U8(0), U8(2), B(CreateClosure), U8(3), U8(0), U8(2),
B(Star), R(4), B(Star), R(3),
B(LdaConstant), U8(2), B(LdaConstant), U8(2),
B(Star), R(5), B(Star), R(4),
B(Mov), R(4), R(6), B(Mov), R(3), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(5), U8(3), B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(3),
B(Star), R(5), B(Star), R(4),
B(Mov), R(6), R(1), B(PopContext), R(2),
B(PopContext), R(3), B(Mov), R(5), R(0),
B(Mov), R(1), R(0),
/* 87 S> */ B(Ldar), R(0), /* 87 S> */ B(Ldar), R(0),
/* 94 E> */ B(Construct), R(0), R(0), U8(0), U8(0), /* 94 E> */ B(Construct), R(0), R(0), U8(0), U8(0),
/* 102 S> */ B(Return), /* 102 S> */ B(Return),
...@@ -195,39 +191,38 @@ snippet: " ...@@ -195,39 +191,38 @@ snippet: "
(class {}) (class {})
class E { static name () {}} class E { static name () {}}
" "
frame size: 8 frame size: 7
parameter count: 1 parameter count: 1
bytecode array length: 73 bytecode array length: 70
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
/* 34 S> */ B(CreateBlockContext), U8(0), /* 34 S> */ B(CreateBlockContext), U8(0),
B(PushContext), R(2), B(PushContext), R(1),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(6), B(Star), R(5),
B(CreateClosure), U8(2), U8(0), U8(2), B(CreateClosure), U8(2), U8(0), U8(2),
B(Star), R(3), B(Star), R(2),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(4), B(Star), R(3),
B(Mov), R(3), R(5), B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(3), B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(3),
B(Star), R(4), B(Star), R(3),
B(PopContext), R(2), B(PopContext), R(1),
B(CreateBlockContext), U8(3), B(CreateBlockContext), U8(3),
B(PushContext), R(2), B(PushContext), R(1),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(6), B(Star), R(5),
B(CreateClosure), U8(5), U8(1), U8(2), B(CreateClosure), U8(5), U8(1), U8(2),
B(Star), R(3), B(Star), R(2),
B(LdaConstant), U8(4), B(LdaConstant), U8(4),
B(Star), R(4), B(Star), R(3),
B(CreateClosure), U8(6), U8(2), U8(2), B(CreateClosure), U8(6), U8(2), U8(2),
B(Star), R(7), B(Star), R(6),
B(Mov), R(3), R(5), B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4), B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
B(Star), R(4), B(Star), R(3),
B(Mov), R(5), R(1), B(PopContext), R(1),
B(PopContext), R(2), B(Mov), R(4), R(0),
B(Mov), R(1), R(0),
B(LdaUndefined), B(LdaUndefined),
/* 74 S> */ B(Return), /* 74 S> */ B(Return),
] ]
......
...@@ -10,29 +10,28 @@ snippet: " ...@@ -10,29 +10,28 @@ snippet: "
class A { constructor(...args) { this.args = args; } } class A { constructor(...args) { this.args = args; } }
new A(...[1, 2, 3]); new A(...[1, 2, 3]);
" "
frame size: 7 frame size: 6
parameter count: 1 parameter count: 1
bytecode array length: 51 bytecode array length: 48
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
B(CreateBlockContext), U8(0), B(CreateBlockContext), U8(0),
B(PushContext), R(2), B(PushContext), R(1),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(6), B(Star), R(5),
B(CreateClosure), U8(2), U8(0), U8(2), B(CreateClosure), U8(2), U8(0), U8(2),
B(Star), R(3), B(Star), R(2),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(4),
B(Mov), R(3), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(3),
B(Star), R(4),
B(Mov), R(5), R(1),
B(PopContext), R(2),
B(Mov), R(1), R(0),
/* 89 S> */ B(CreateArrayLiteral), U8(3), U8(0), U8(37),
B(Star), R(3), B(Star), R(3),
B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(3),
B(Star), R(3),
B(PopContext), R(1),
B(Mov), R(4), R(0),
/* 89 S> */ B(CreateArrayLiteral), U8(3), U8(0), U8(37),
B(Star), R(2),
B(Ldar), R(0), B(Ldar), R(0),
/* 89 E> */ B(ConstructWithSpread), R(0), R(3), U8(1), U8(1), /* 89 E> */ B(ConstructWithSpread), R(0), R(2), U8(1), U8(1),
B(LdaUndefined), B(LdaUndefined),
/* 110 S> */ B(Return), /* 110 S> */ B(Return),
] ]
...@@ -50,31 +49,30 @@ snippet: " ...@@ -50,31 +49,30 @@ snippet: "
class A { constructor(...args) { this.args = args; } } class A { constructor(...args) { this.args = args; } }
new A(0, ...[1, 2, 3]); new A(0, ...[1, 2, 3]);
" "
frame size: 7 frame size: 6
parameter count: 1 parameter count: 1
bytecode array length: 54 bytecode array length: 51
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
B(CreateBlockContext), U8(0), B(CreateBlockContext), U8(0),
B(PushContext), R(2), B(PushContext), R(1),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(6), B(Star), R(5),
B(CreateClosure), U8(2), U8(0), U8(2), B(CreateClosure), U8(2), U8(0), U8(2),
B(Star), R(3), B(Star), R(2),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(4),
B(Mov), R(3), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(3),
B(Star), R(4),
B(Mov), R(5), R(1),
B(PopContext), R(2),
B(Mov), R(1), R(0),
/* 89 S> */ B(LdaZero),
B(Star), R(3), B(Star), R(3),
B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(3),
B(Star), R(3),
B(PopContext), R(1),
B(Mov), R(4), R(0),
/* 89 S> */ B(LdaZero),
B(Star), R(2),
B(CreateArrayLiteral), U8(3), U8(0), U8(37), B(CreateArrayLiteral), U8(3), U8(0), U8(37),
B(Star), R(4), B(Star), R(3),
B(Ldar), R(0), B(Ldar), R(0),
/* 89 E> */ B(ConstructWithSpread), R(0), R(3), U8(2), U8(1), /* 89 E> */ B(ConstructWithSpread), R(0), R(2), U8(2), U8(1),
B(LdaUndefined), B(LdaUndefined),
/* 113 S> */ B(Return), /* 113 S> */ B(Return),
] ]
...@@ -92,52 +90,51 @@ snippet: " ...@@ -92,52 +90,51 @@ snippet: "
class A { constructor(...args) { this.args = args; } } class A { constructor(...args) { this.args = args; } }
new A(0, ...[1, 2, 3], 4); new A(0, ...[1, 2, 3], 4);
" "
frame size: 8 frame size: 7
parameter count: 1 parameter count: 1
bytecode array length: 118 bytecode array length: 115
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
B(CreateBlockContext), U8(0), B(CreateBlockContext), U8(0),
B(PushContext), R(2), B(PushContext), R(1),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(6), B(Star), R(5),
B(CreateClosure), U8(2), U8(0), U8(2), B(CreateClosure), U8(2), U8(0), U8(2),
B(Star), R(3), B(Star), R(2),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(4), B(Star), R(3),
B(Mov), R(3), R(5), B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(3), B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(3),
B(Star), R(4), B(Star), R(3),
B(Mov), R(5), R(1), B(PopContext), R(1),
B(PopContext), R(2), B(Mov), R(4), R(0),
B(Mov), R(1), R(0),
/* 89 S> */ B(CreateArrayLiteral), U8(3), U8(0), U8(37), /* 89 S> */ B(CreateArrayLiteral), U8(3), U8(0), U8(37),
B(Star), R(4),
B(LdaConstant), U8(4),
B(Star), R(3), B(Star), R(3),
B(LdaConstant), U8(4),
B(Star), R(2),
/* 101 S> */ B(CreateArrayLiteral), U8(5), U8(1), U8(37), /* 101 S> */ B(CreateArrayLiteral), U8(5), U8(1), U8(37),
B(Star), R(7),
B(GetIterator), R(7), U8(2), U8(4),
B(Star), R(6), B(Star), R(6),
B(LdaNamedProperty), R(6), U8(6), U8(6), B(GetIterator), R(6), U8(2), U8(4),
B(Star), R(5), B(Star), R(5),
B(Mov), R(1), R(2), B(LdaNamedProperty), R(5), U8(6), U8(6),
B(CallProperty0), R(5), R(6), U8(15), B(Star), R(4),
B(Star), R(7), B(Mov), R(0), R(1),
B(CallProperty0), R(4), R(5), U8(15),
B(Star), R(6),
B(JumpIfJSReceiver), U8(7), B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(7), U8(1), B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(6), U8(1),
B(LdaNamedProperty), R(7), U8(7), U8(17), B(LdaNamedProperty), R(6), U8(7), U8(17),
B(JumpIfToBooleanTrue), U8(19), B(JumpIfToBooleanTrue), U8(19),
B(LdaNamedProperty), R(7), U8(8), U8(8), B(LdaNamedProperty), R(6), U8(8), U8(8),
B(StaInArrayLiteral), R(4), R(3), U8(13), B(StaInArrayLiteral), R(3), R(2), U8(13),
B(Ldar), R(3), B(Ldar), R(2),
B(Inc), U8(12), B(Inc), U8(12),
B(Star), R(3), B(Star), R(2),
B(JumpLoop), U8(33), I8(0), B(JumpLoop), U8(33), I8(0),
B(LdaSmi), I8(4), B(LdaSmi), I8(4),
B(StaInArrayLiteral), R(4), R(3), U8(13), B(StaInArrayLiteral), R(3), R(2), U8(13),
B(Mov), R(4), R(3), B(Mov), R(3), R(2),
B(CallJSRuntime), U8(%reflect_construct), R(2), U8(2), B(CallJSRuntime), U8(%reflect_construct), R(1), U8(2),
B(LdaUndefined), B(LdaUndefined),
/* 116 S> */ B(Return), /* 116 S> */ B(Return),
] ]
......
...@@ -14,31 +14,30 @@ snippet: " ...@@ -14,31 +14,30 @@ snippet: "
} }
} }
" "
frame size: 7 frame size: 6
parameter count: 1 parameter count: 1
bytecode array length: 55 bytecode array length: 52
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
B(CreateBlockContext), U8(0), B(CreateBlockContext), U8(0),
B(PushContext), R(2), B(PushContext), R(1),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(6), B(Star), R(5),
B(CreateClosure), U8(2), U8(0), U8(2), B(CreateClosure), U8(2), U8(0), U8(2),
B(Star), R(3), B(Star), R(2),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(4), B(Star), R(3),
B(CreateClosure), U8(3), U8(1), U8(2), B(CreateClosure), U8(3), U8(1), U8(2),
B(StaCurrentContextSlot), U8(4), B(StaCurrentContextSlot), U8(4),
B(Mov), R(3), R(5), B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(3), B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(3),
B(Star), R(4), B(Star), R(3),
B(Mov), R(5), R(1),
B(LdaConstant), U8(4), B(LdaConstant), U8(4),
B(Star), R(5), B(Star), R(4),
B(CallRuntime), U16(Runtime::kCreatePrivateNameSymbol), R(5), U8(1), B(CallRuntime), U16(Runtime::kCreatePrivateNameSymbol), R(4), U8(1),
B(StaCurrentContextSlot), U8(5), B(StaCurrentContextSlot), U8(5),
B(PopContext), R(2), B(PopContext), R(1),
B(Mov), R(1), R(0), B(Mov), R(2), R(0),
B(LdaUndefined), B(LdaUndefined),
/* 77 S> */ B(Return), /* 77 S> */ B(Return),
] ]
...@@ -63,50 +62,48 @@ snippet: " ...@@ -63,50 +62,48 @@ snippet: "
} }
} }
" "
frame size: 9 frame size: 7
parameter count: 1 parameter count: 1
bytecode array length: 107 bytecode array length: 101
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
B(CreateBlockContext), U8(0), B(CreateBlockContext), U8(0),
B(PushContext), R(4), B(PushContext), R(2),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(8), B(Star), R(6),
B(CreateClosure), U8(2), U8(0), U8(2), B(CreateClosure), U8(2), U8(0), U8(2),
B(Star), R(5), B(Star), R(3),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(6), B(Star), R(4),
B(CreateClosure), U8(3), U8(1), U8(2), B(CreateClosure), U8(3), U8(1), U8(2),
B(StaCurrentContextSlot), U8(4), B(StaCurrentContextSlot), U8(4),
B(Mov), R(5), R(7), B(Mov), R(3), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(6), U8(3), B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(3),
B(Star), R(6), B(Star), R(4),
B(Mov), R(7), R(3),
B(LdaConstant), U8(4), B(LdaConstant), U8(4),
B(Star), R(7), B(Star), R(5),
B(CallRuntime), U16(Runtime::kCreatePrivateNameSymbol), R(7), U8(1), B(CallRuntime), U16(Runtime::kCreatePrivateNameSymbol), R(5), U8(1),
B(StaCurrentContextSlot), U8(5), B(StaCurrentContextSlot), U8(5),
B(PopContext), R(4), B(PopContext), R(2),
B(Mov), R(3), R(0), B(Mov), R(3), R(0),
/* 38 E> */ B(CreateBlockContext), U8(5), /* 38 E> */ B(CreateBlockContext), U8(5),
B(PushContext), R(4), B(PushContext), R(2),
/* 93 E> */ B(CreateClosure), U8(7), U8(2), U8(2), /* 93 E> */ B(CreateClosure), U8(7), U8(2), U8(2),
B(Star), R(5), B(Star), R(3),
B(LdaConstant), U8(6), B(LdaConstant), U8(6),
B(Star), R(6), B(Star), R(4),
B(CreateClosure), U8(8), U8(3), U8(2), B(CreateClosure), U8(8), U8(3), U8(2),
B(StaCurrentContextSlot), U8(4), B(StaCurrentContextSlot), U8(4),
B(Mov), R(5), R(7), B(Mov), R(3), R(5),
B(Mov), R(3), R(8), B(Mov), R(0), R(6),
B(CallRuntime), U16(Runtime::kDefineClass), R(6), U8(3), B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(3),
B(Star), R(6), B(Star), R(4),
B(Mov), R(7), R(2),
B(LdaConstant), U8(9), B(LdaConstant), U8(9),
B(Star), R(7), B(Star), R(5),
B(CallRuntime), U16(Runtime::kCreatePrivateNameSymbol), R(7), U8(1), B(CallRuntime), U16(Runtime::kCreatePrivateNameSymbol), R(5), U8(1),
B(StaCurrentContextSlot), U8(5), B(StaCurrentContextSlot), U8(5),
B(PopContext), R(4), B(PopContext), R(2),
B(Mov), R(2), R(1), B(Mov), R(3), R(1),
B(LdaUndefined), B(LdaUndefined),
/* 126 S> */ B(Return), /* 126 S> */ B(Return),
] ]
...@@ -134,50 +131,48 @@ snippet: " ...@@ -134,50 +131,48 @@ snippet: "
} }
} }
" "
frame size: 10 frame size: 8
parameter count: 1 parameter count: 1
bytecode array length: 106 bytecode array length: 100
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
B(CreateBlockContext), U8(0), B(CreateBlockContext), U8(0),
B(PushContext), R(4), B(PushContext), R(2),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(8), B(Star), R(6),
B(CreateClosure), U8(2), U8(0), U8(2), B(CreateClosure), U8(2), U8(0), U8(2),
B(Star), R(5), B(Star), R(3),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(6), B(Star), R(4),
B(CreateClosure), U8(3), U8(1), U8(2), B(CreateClosure), U8(3), U8(1), U8(2),
B(Star), R(9), B(Star), R(7),
B(Mov), R(5), R(7), B(Mov), R(3), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(6), U8(4), B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4),
B(Star), R(6), B(Star), R(4),
B(Mov), R(7), R(3), B(PopContext), R(2),
B(PopContext), R(4), B(Mov), R(5), R(0),
B(Mov), R(3), R(0),
/* 38 E> */ B(CreateBlockContext), U8(4), /* 38 E> */ B(CreateBlockContext), U8(4),
B(PushContext), R(4), B(PushContext), R(2),
/* 77 E> */ B(CreateClosure), U8(6), U8(2), U8(2), /* 77 E> */ B(CreateClosure), U8(6), U8(2), U8(2),
B(Star), R(5), B(Star), R(3),
B(LdaConstant), U8(5), B(LdaConstant), U8(5),
B(Star), R(6), B(Star), R(4),
B(CreateClosure), U8(7), U8(3), U8(2), B(CreateClosure), U8(7), U8(3), U8(2),
B(StaCurrentContextSlot), U8(4), B(StaCurrentContextSlot), U8(4),
B(Mov), R(5), R(7), B(Mov), R(3), R(5),
B(Mov), R(3), R(8), B(Mov), R(0), R(6),
B(CallRuntime), U16(Runtime::kDefineClass), R(6), U8(3), B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(3),
B(Star), R(6), B(Star), R(4),
B(Mov), R(7), R(2),
B(LdaConstant), U8(8), B(LdaConstant), U8(8),
B(Star), R(7), B(Star), R(5),
B(CallRuntime), U16(Runtime::kCreatePrivateNameSymbol), R(7), U8(1), B(CallRuntime), U16(Runtime::kCreatePrivateNameSymbol), R(5), U8(1),
B(StaCurrentContextSlot), U8(5), B(StaCurrentContextSlot), U8(5),
B(LdaCurrentContextSlot), U8(4), B(LdaCurrentContextSlot), U8(4),
B(Star), R(8), B(Star), R(6),
B(Ldar), R(6), B(Ldar), R(4),
B(StaNamedProperty), R(8), U8(9), U8(0), B(StaNamedProperty), R(6), U8(9), U8(0),
B(PopContext), R(4), B(PopContext), R(2),
B(Mov), R(2), R(1), B(Mov), R(3), R(1),
B(LdaUndefined), B(LdaUndefined),
/* 118 S> */ B(Return), /* 118 S> */ B(Return),
] ]
......
...@@ -21,59 +21,57 @@ snippet: " ...@@ -21,59 +21,57 @@ snippet: "
new B; new B;
} }
" "
frame size: 10 frame size: 8
parameter count: 1 parameter count: 1
bytecode array length: 125 bytecode array length: 119
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
B(CreateBlockContext), U8(0), B(CreateBlockContext), U8(0),
B(PushContext), R(4), B(PushContext), R(2),
B(LdaTheHole), B(LdaTheHole),
B(StaCurrentContextSlot), U8(4), B(StaCurrentContextSlot), U8(4),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(8), B(Star), R(6),
B(CreateClosure), U8(2), U8(0), U8(2), B(CreateClosure), U8(2), U8(0), U8(2),
B(Star), R(5), B(Star), R(3),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(6), B(Star), R(4),
/* 60 S> */ B(LdaConstant), U8(3), /* 60 S> */ B(LdaConstant), U8(3),
B(StaCurrentContextSlot), U8(4), B(StaCurrentContextSlot), U8(4),
B(Star), R(9),
B(Mov), R(5), R(7),
B(CallRuntime), U16(Runtime::kDefineClass), R(6), U8(4),
B(Star), R(6),
B(Mov), R(7), R(3),
B(CreateClosure), U8(4), U8(1), U8(2),
B(Star), R(7), B(Star), R(7),
B(StaNamedProperty), R(5), U8(5), U8(0), B(Mov), R(3), R(5),
B(PopContext), R(4), B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4),
B(Star), R(4),
B(CreateClosure), U8(4), U8(1), U8(2),
B(Star), R(5),
B(StaNamedProperty), R(3), U8(5), U8(0),
B(PopContext), R(2),
B(Mov), R(3), R(0), B(Mov), R(3), R(0),
/* 38 E> */ B(CreateBlockContext), U8(6), /* 38 E> */ B(CreateBlockContext), U8(6),
B(PushContext), R(4), B(PushContext), R(2),
B(LdaTheHole), B(LdaTheHole),
B(StaCurrentContextSlot), U8(4), B(StaCurrentContextSlot), U8(4),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(8), B(Star), R(6),
B(CreateClosure), U8(8), U8(2), U8(2), B(CreateClosure), U8(8), U8(2), U8(2),
B(Star), R(5), B(Star), R(3),
B(LdaConstant), U8(7), B(LdaConstant), U8(7),
B(Star), R(6), B(Star), R(4),
/* 99 S> */ B(LdaConstant), U8(3), /* 99 S> */ B(LdaConstant), U8(3),
B(StaCurrentContextSlot), U8(4), B(StaCurrentContextSlot), U8(4),
B(Star), R(9),
B(Mov), R(5), R(7),
B(CallRuntime), U16(Runtime::kDefineClass), R(6), U8(4),
B(Star), R(6),
B(Mov), R(7), R(2),
B(CreateClosure), U8(9), U8(3), U8(2),
B(Star), R(7), B(Star), R(7),
B(StaNamedProperty), R(5), U8(5), U8(2), B(Mov), R(3), R(5),
B(PopContext), R(4), B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4),
B(Mov), R(2), R(1), B(Star), R(4),
/* 120 S> */ B(Ldar), R(3), B(CreateClosure), U8(9), U8(3), U8(2),
/* 120 E> */ B(Construct), R(3), R(0), U8(0), U8(4), B(Star), R(5),
/* 129 S> */ B(Ldar), R(2), B(StaNamedProperty), R(3), U8(5), U8(2),
/* 129 E> */ B(Construct), R(2), R(0), U8(0), U8(6), B(PopContext), R(2),
B(Mov), R(3), R(1),
/* 120 S> */ B(Ldar), R(0),
/* 120 E> */ B(Construct), R(0), R(0), U8(0), U8(4),
/* 129 S> */ B(Ldar), R(1),
/* 129 E> */ B(Construct), R(1), R(0), U8(0), U8(6),
B(LdaUndefined), B(LdaUndefined),
/* 138 S> */ B(Return), /* 138 S> */ B(Return),
] ]
...@@ -122,100 +120,97 @@ snippet: " ...@@ -122,100 +120,97 @@ snippet: "
new C; new C;
} }
" "
frame size: 15 frame size: 12
parameter count: 1 parameter count: 1
bytecode array length: 238 bytecode array length: 229
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
B(CreateBlockContext), U8(0), B(CreateBlockContext), U8(0),
B(PushContext), R(6), B(PushContext), R(3),
B(LdaTheHole), B(LdaTheHole),
B(StaCurrentContextSlot), U8(4), B(StaCurrentContextSlot), U8(4),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(14),
B(CreateClosure), U8(3), U8(0), U8(2),
B(Star), R(11), B(Star), R(11),
B(CreateClosure), U8(3), U8(0), U8(2),
B(Star), R(8),
B(LdaConstant), U8(2), B(LdaConstant), U8(2),
B(Star), R(12), B(Star), R(9),
B(Mov), R(11), R(13), B(Mov), R(8), R(10),
B(CallRuntime), U16(Runtime::kDefineClass), R(12), U8(3), B(CallRuntime), U16(Runtime::kDefineClass), R(9), U8(3),
B(Star), R(12), B(Star), R(9),
B(CreateClosure), U8(4), U8(1), U8(2), B(CreateClosure), U8(4), U8(1), U8(2),
B(Star), R(7), B(Star), R(4),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(8), B(Star), R(5),
/* 77 S> */ B(LdaConstant), U8(5), /* 77 S> */ B(LdaConstant), U8(5),
B(StaCurrentContextSlot), U8(4), B(StaCurrentContextSlot), U8(4),
B(Star), R(11),
B(Mov), R(7), R(9),
B(Mov), R(13), R(10),
B(CallRuntime), U16(Runtime::kDefineClass), R(8), U8(4),
B(Star), R(8), B(Star), R(8),
B(Mov), R(9), R(5), B(Mov), R(4), R(6),
B(Mov), R(10), R(7),
B(CallRuntime), U16(Runtime::kDefineClass), R(5), U8(4),
B(Star), R(5),
B(CreateClosure), U8(6), U8(2), U8(2), B(CreateClosure), U8(6), U8(2), U8(2),
B(Star), R(9), B(Star), R(6),
B(StaNamedProperty), R(7), U8(7), U8(0), B(StaNamedProperty), R(4), U8(7), U8(0),
B(PopContext), R(6), B(PopContext), R(3),
B(Mov), R(5), R(0), B(Mov), R(4), R(0),
/* 38 E> */ B(CreateBlockContext), U8(8), /* 38 E> */ B(CreateBlockContext), U8(8),
B(PushContext), R(6), B(PushContext), R(3),
B(LdaTheHole), B(LdaTheHole),
B(StaCurrentContextSlot), U8(4), B(StaCurrentContextSlot), U8(4),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(14),
B(CreateClosure), U8(11), U8(3), U8(2),
B(Star), R(11), B(Star), R(11),
B(CreateClosure), U8(11), U8(3), U8(2),
B(Star), R(8),
B(LdaConstant), U8(10), B(LdaConstant), U8(10),
B(Star), R(12), B(Star), R(9),
B(Mov), R(11), R(13), B(Mov), R(8), R(10),
B(CallRuntime), U16(Runtime::kDefineClass), R(12), U8(3), B(CallRuntime), U16(Runtime::kDefineClass), R(9), U8(3),
B(Star), R(12), B(Star), R(9),
B(CreateClosure), U8(12), U8(4), U8(2), B(CreateClosure), U8(12), U8(4), U8(2),
B(Star), R(7), B(Star), R(4),
B(LdaConstant), U8(9), B(LdaConstant), U8(9),
B(Star), R(8), B(Star), R(5),
/* 133 S> */ B(LdaConstant), U8(5), /* 133 S> */ B(LdaConstant), U8(5),
B(StaCurrentContextSlot), U8(4), B(StaCurrentContextSlot), U8(4),
B(Star), R(11),
B(CreateClosure), U8(13), U8(5), U8(2),
B(Star), R(12),
B(Mov), R(7), R(9),
B(Mov), R(13), R(10),
B(CallRuntime), U16(Runtime::kDefineClass), R(8), U8(5),
B(Star), R(8), B(Star), R(8),
B(Mov), R(9), R(4), B(CreateClosure), U8(13), U8(5), U8(2),
B(CreateClosure), U8(14), U8(6), U8(2),
B(Star), R(9), B(Star), R(9),
B(StaNamedProperty), R(7), U8(7), U8(2), B(Mov), R(4), R(6),
B(PopContext), R(6), B(Mov), R(10), R(7),
B(CallRuntime), U16(Runtime::kDefineClass), R(5), U8(5),
B(Star), R(5),
B(CreateClosure), U8(14), U8(6), U8(2),
B(Star), R(6),
B(StaNamedProperty), R(4), U8(7), U8(2),
B(PopContext), R(3),
B(Mov), R(4), R(1), B(Mov), R(4), R(1),
/* 90 E> */ B(CreateBlockContext), U8(15), /* 90 E> */ B(CreateBlockContext), U8(15),
B(PushContext), R(6), B(PushContext), R(3),
B(LdaTheHole), B(LdaTheHole),
B(StaCurrentContextSlot), U8(4), B(StaCurrentContextSlot), U8(4),
/* 236 E> */ B(CreateClosure), U8(17), U8(7), U8(2), /* 236 E> */ B(CreateClosure), U8(17), U8(7), U8(2),
B(Star), R(7), B(Star), R(4),
B(LdaConstant), U8(16), B(LdaConstant), U8(16),
B(Star), R(8), B(Star), R(5),
/* 256 S> */ B(LdaConstant), U8(5), /* 256 S> */ B(LdaConstant), U8(5),
B(StaCurrentContextSlot), U8(4), B(StaCurrentContextSlot), U8(4),
B(Star), R(11),
B(Mov), R(7), R(9),
B(Mov), R(4), R(10),
B(CallRuntime), U16(Runtime::kDefineClass), R(8), U8(4),
B(Star), R(8), B(Star), R(8),
B(Mov), R(9), R(3), B(Mov), R(4), R(6),
B(Mov), R(1), R(7),
B(CallRuntime), U16(Runtime::kDefineClass), R(5), U8(4),
B(Star), R(5),
B(CreateClosure), U8(18), U8(8), U8(2), B(CreateClosure), U8(18), U8(8), U8(2),
B(Star), R(9), B(Star), R(6),
B(StaNamedProperty), R(7), U8(7), U8(4), B(StaNamedProperty), R(4), U8(7), U8(4),
B(PopContext), R(6), B(PopContext), R(3),
B(Mov), R(3), R(2), B(Mov), R(4), R(2),
/* 329 S> */ B(Ldar), R(5), /* 329 S> */ B(Ldar), R(0),
/* 329 E> */ B(Construct), R(5), R(0), U8(0), U8(6), /* 329 E> */ B(Construct), R(0), R(0), U8(0), U8(6),
/* 338 S> */ B(Ldar), R(4), /* 338 S> */ B(Ldar), R(1),
/* 338 E> */ B(Construct), R(4), R(0), U8(0), U8(8), /* 338 E> */ B(Construct), R(1), R(0), U8(0), U8(8),
/* 347 S> */ B(Ldar), R(3), /* 347 S> */ B(Ldar), R(2),
/* 347 E> */ B(Construct), R(3), R(0), U8(0), U8(10), /* 347 E> */ B(Construct), R(2), R(0), U8(0), U8(10),
B(LdaUndefined), B(LdaUndefined),
/* 356 S> */ B(Return), /* 356 S> */ B(Return),
] ]
......
#
# Autogenerated by generate-bytecode-expectations.
#
---
wrap: no
test function name: test
private methods: yes
---
snippet: "
class A {
static #a() { return 1; }
static test() { return this.#a(); }
}
var test = A.test;
test();
"
frame size: 4
parameter count: 1
bytecode array length: 36
bytecodes: [
/* 51 E> */ B(StackCheck),
/* 56 S> */ B(LdaCurrentContextSlot), U8(5),
B(TestReferenceEqual), R(this),
B(Mov), R(this), R(1),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(259),
B(Star), R(2),
B(LdaConstant), U8(0),
B(Star), R(3),
B(CallRuntime), U16(Runtime::kNewTypeError), R(2), U8(2),
B(Throw),
B(LdaCurrentContextSlot), U8(4),
B(Star), R(0),
/* 70 E> */ B(CallAnyReceiver), R(0), R(1), U8(1), U8(0),
/* 73 S> */ B(Return),
]
constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE ["#a"],
]
handlers: [
]
---
snippet: "
class B {
static #b() { return 1; }
static test() { this.#b = 1; }
}
var test = B.test;
test();
"
frame size: 2
parameter count: 1
bytecode array length: 17
bytecodes: [
/* 51 E> */ B(StackCheck),
/* 56 S> */ B(Wide), B(LdaSmi), I16(261),
B(Star), R(0),
B(LdaConstant), U8(0),
B(Star), R(1),
/* 64 E> */ B(CallRuntime), U16(Runtime::kNewTypeError), R(0), U8(2),
B(Throw),
]
constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE ["#b"],
]
handlers: [
]
---
snippet: "
class C {
static #c() { return 1; }
static test() { this.#c++; }
}
var test = C.test;
test();
"
frame size: 2
parameter count: 1
bytecode array length: 17
bytecodes: [
/* 51 E> */ B(StackCheck),
/* 56 S> */ B(Wide), B(LdaSmi), I16(261),
B(Star), R(0),
B(LdaConstant), U8(0),
B(Star), R(1),
B(CallRuntime), U16(Runtime::kNewTypeError), R(0), U8(2),
B(Throw),
]
constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE ["#c"],
]
handlers: [
]
---
snippet: "
class D {
static get #d() { return 1; }
static set #d(val) { }
static test() {
this.#d++;
this.#d = 1;
return this.#d;
}
}
var test = D.test;
test();
"
frame size: 5
parameter count: 1
bytecode array length: 143
bytecodes: [
/* 81 E> */ B(StackCheck),
/* 90 S> */ B(LdaCurrentContextSlot), U8(4),
B(Star), R(1),
B(LdaCurrentContextSlot), U8(5),
/* 94 E> */ B(TestReferenceEqual), R(this),
B(Mov), R(this), R(0),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(259),
B(Star), R(2),
B(LdaConstant), U8(0),
B(Star), R(3),
B(CallRuntime), U16(Runtime::kNewTypeError), R(2), U8(2),
B(Throw),
B(CallRuntime), U16(Runtime::kLoadPrivateGetter), R(1), U8(1),
B(Star), R(2),
B(CallProperty0), R(2), R(0), U8(0),
B(Inc), U8(2),
B(Star), R(2),
/* 97 E> */ B(CallRuntime), U16(Runtime::kLoadPrivateSetter), R(1), U8(1),
B(Star), R(3),
B(CallProperty1), R(3), R(0), R(2), U8(3),
/* 105 S> */ B(LdaSmi), I8(1),
B(Star), R(0),
B(LdaCurrentContextSlot), U8(4),
B(Star), R(2),
B(LdaCurrentContextSlot), U8(5),
/* 109 E> */ B(TestReferenceEqual), R(this),
B(Mov), R(this), R(1),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(260),
B(Star), R(3),
B(LdaConstant), U8(0),
B(Star), R(4),
B(CallRuntime), U16(Runtime::kNewTypeError), R(3), U8(2),
B(Throw),
B(CallRuntime), U16(Runtime::kLoadPrivateSetter), R(2), U8(1),
B(Star), R(3),
B(CallProperty1), R(3), R(1), R(0), U8(5),
/* 122 S> */ B(LdaCurrentContextSlot), U8(4),
B(Star), R(1),
B(LdaCurrentContextSlot), U8(5),
/* 133 E> */ B(TestReferenceEqual), R(this),
B(Mov), R(this), R(0),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(259),
B(Star), R(2),
B(LdaConstant), U8(0),
B(Star), R(3),
B(CallRuntime), U16(Runtime::kNewTypeError), R(2), U8(2),
B(Throw),
B(CallRuntime), U16(Runtime::kLoadPrivateGetter), R(1), U8(1),
B(Star), R(2),
B(CallProperty0), R(2), R(0), U8(7),
/* 137 S> */ B(Return),
]
constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE ["#d"],
]
handlers: [
]
---
snippet: "
class E {
static get #e() { return 1; }
static test() { this.#e++; }
}
var test = E.test;
test();
"
frame size: 2
parameter count: 1
bytecode array length: 17
bytecodes: [
/* 55 E> */ B(StackCheck),
/* 60 S> */ B(Wide), B(LdaSmi), I16(263),
B(Star), R(0),
B(LdaConstant), U8(0),
B(Star), R(1),
B(CallRuntime), U16(Runtime::kNewTypeError), R(0), U8(2),
B(Throw),
]
constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE ["#e"],
]
handlers: [
]
---
snippet: "
class F {
static set #f(val) { }
static test() { this.#f++; }
}
var test = F.test;
test();
"
frame size: 2
parameter count: 1
bytecode array length: 17
bytecodes: [
/* 48 E> */ B(StackCheck),
/* 53 S> */ B(Wide), B(LdaSmi), I16(262),
B(Star), R(0),
B(LdaConstant), U8(0),
B(Star), R(1),
B(CallRuntime), U16(Runtime::kNewTypeError), R(0), U8(2),
B(Throw),
]
constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE ["#f"],
]
handlers: [
]
---
snippet: "
class G {
static get #d() { return 1; }
static test() { this.#d = 1; }
}
var test = G.test;
test();
"
frame size: 2
parameter count: 1
bytecode array length: 17
bytecodes: [
/* 55 E> */ B(StackCheck),
/* 60 S> */ B(Wide), B(LdaSmi), I16(263),
B(Star), R(0),
B(LdaConstant), U8(0),
B(Star), R(1),
/* 68 E> */ B(CallRuntime), U16(Runtime::kNewTypeError), R(0), U8(2),
B(Throw),
]
constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE ["#d"],
]
handlers: [
]
---
snippet: "
class H {
set #h(val) { }
static test() { this.#h; }
}
var test = H.test;
test();
"
frame size: 3
parameter count: 1
bytecode array length: 17
bytecodes: [
/* 41 E> */ B(StackCheck),
/* 46 S> */ B(Wide), B(LdaSmi), I16(262),
B(Star), R(1),
B(LdaConstant), U8(0),
B(Star), R(2),
B(CallRuntime), U16(Runtime::kNewTypeError), R(1), U8(2),
B(Throw),
]
constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE ["#h"],
]
handlers: [
]
...@@ -14,31 +14,26 @@ snippet: " ...@@ -14,31 +14,26 @@ snippet: "
} }
} }
" "
frame size: 7 frame size: 6
parameter count: 1 parameter count: 1
bytecode array length: 55 bytecode array length: 41
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
B(CreateBlockContext), U8(0), B(CreateBlockContext), U8(0),
B(PushContext), R(2), B(PushContext), R(1),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(6), B(Star), R(5),
B(CreateClosure), U8(2), U8(0), U8(2), B(CreateClosure), U8(2), U8(0), U8(2),
B(Star), R(3), B(Star), R(2),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(4), B(Star), R(3),
B(CreateClosure), U8(3), U8(1), U8(2), B(CreateClosure), U8(3), U8(1), U8(2),
B(StaCurrentContextSlot), U8(4), B(StaCurrentContextSlot), U8(4),
B(Mov), R(3), R(5), B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(3), B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(3),
B(Star), R(4), B(Star), R(3),
B(Mov), R(5), R(1), B(PopContext), R(1),
B(LdaConstant), U8(4), B(Mov), R(4), R(0),
B(Star), R(5),
B(CallRuntime), U16(Runtime::kCreatePrivateNameSymbol), R(5), U8(1),
B(StaCurrentContextSlot), U8(5),
B(PopContext), R(2),
B(Mov), R(1), R(0),
B(LdaUndefined), B(LdaUndefined),
/* 84 S> */ B(Return), /* 84 S> */ B(Return),
] ]
...@@ -47,7 +42,6 @@ constant pool: [ ...@@ -47,7 +42,6 @@ constant pool: [
FIXED_ARRAY_TYPE, FIXED_ARRAY_TYPE,
SHARED_FUNCTION_INFO_TYPE, SHARED_FUNCTION_INFO_TYPE,
SHARED_FUNCTION_INFO_TYPE, SHARED_FUNCTION_INFO_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["A"],
] ]
handlers: [ handlers: [
] ]
...@@ -60,35 +54,30 @@ snippet: " ...@@ -60,35 +54,30 @@ snippet: "
} }
} }
" "
frame size: 8 frame size: 6
parameter count: 1 parameter count: 1
bytecode array length: 65 bytecode array length: 51
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
B(CreateBlockContext), U8(0), B(CreateBlockContext), U8(0),
B(PushContext), R(2), B(PushContext), R(1),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(6), B(Star), R(5),
B(CreateClosure), U8(2), U8(0), U8(2), B(CreateClosure), U8(2), U8(0), U8(2),
B(Star), R(3), B(Star), R(2),
B(LdaConstant), U8(1), 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(Star), R(4), B(Star), R(4),
B(Mov), R(3), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(3),
B(Star), R(4),
B(Mov), R(5), R(1),
B(LdaConstant), U8(3),
B(Star), R(5),
B(CallRuntime), U16(Runtime::kCreatePrivateNameSymbol), R(5), U8(1),
B(StaCurrentContextSlot), U8(5),
B(CreateClosure), U8(4), U8(1), U8(2),
B(Star), R(6),
B(LdaNull), B(LdaNull),
B(Star), R(7), B(Star), R(5),
B(CallRuntime), U16(Runtime::kCreatePrivateAccessors), R(6), U8(2), B(CallRuntime), U16(Runtime::kCreatePrivateAccessors), R(4), U8(2),
B(StaCurrentContextSlot), U8(4), B(StaCurrentContextSlot), U8(4),
B(PopContext), R(2), B(PopContext), R(1),
B(Mov), R(1), R(0), B(Mov), R(2), R(0),
B(LdaUndefined), B(LdaUndefined),
/* 88 S> */ B(Return), /* 88 S> */ B(Return),
] ]
...@@ -96,7 +85,6 @@ constant pool: [ ...@@ -96,7 +85,6 @@ constant pool: [
SCOPE_INFO_TYPE, SCOPE_INFO_TYPE,
FIXED_ARRAY_TYPE, FIXED_ARRAY_TYPE,
SHARED_FUNCTION_INFO_TYPE, SHARED_FUNCTION_INFO_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["A"],
SHARED_FUNCTION_INFO_TYPE, SHARED_FUNCTION_INFO_TYPE,
] ]
handlers: [ handlers: [
...@@ -110,35 +98,30 @@ snippet: " ...@@ -110,35 +98,30 @@ snippet: "
} }
} }
" "
frame size: 8 frame size: 6
parameter count: 1 parameter count: 1
bytecode array length: 65 bytecode array length: 51
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
B(CreateBlockContext), U8(0), B(CreateBlockContext), U8(0),
B(PushContext), R(2), B(PushContext), R(1),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(6), B(Star), R(5),
B(CreateClosure), U8(2), U8(0), U8(2), B(CreateClosure), U8(2), U8(0), U8(2),
B(Star), R(3), B(Star), R(2),
B(LdaConstant), U8(1), 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(LdaNull),
B(Star), R(4), B(Star), R(4),
B(Mov), R(3), R(5), B(CreateClosure), U8(3), U8(1), U8(2),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(3),
B(Star), R(4),
B(Mov), R(5), R(1),
B(LdaConstant), U8(3),
B(Star), R(5), B(Star), R(5),
B(CallRuntime), U16(Runtime::kCreatePrivateNameSymbol), R(5), U8(1), B(CallRuntime), U16(Runtime::kCreatePrivateAccessors), R(4), U8(2),
B(StaCurrentContextSlot), U8(5),
B(LdaNull),
B(Star), R(6),
B(CreateClosure), U8(4), U8(1), U8(2),
B(Star), R(7),
B(CallRuntime), U16(Runtime::kCreatePrivateAccessors), R(6), U8(2),
B(StaCurrentContextSlot), U8(4), B(StaCurrentContextSlot), U8(4),
B(PopContext), R(2), B(PopContext), R(1),
B(Mov), R(1), R(0), B(Mov), R(2), R(0),
B(LdaUndefined), B(LdaUndefined),
/* 81 S> */ B(Return), /* 81 S> */ B(Return),
] ]
...@@ -146,7 +129,6 @@ constant pool: [ ...@@ -146,7 +129,6 @@ constant pool: [
SCOPE_INFO_TYPE, SCOPE_INFO_TYPE,
FIXED_ARRAY_TYPE, FIXED_ARRAY_TYPE,
SHARED_FUNCTION_INFO_TYPE, SHARED_FUNCTION_INFO_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["A"],
SHARED_FUNCTION_INFO_TYPE, SHARED_FUNCTION_INFO_TYPE,
] ]
handlers: [ handlers: [
...@@ -161,35 +143,30 @@ snippet: " ...@@ -161,35 +143,30 @@ snippet: "
} }
} }
" "
frame size: 8 frame size: 6
parameter count: 1 parameter count: 1
bytecode array length: 68 bytecode array length: 54
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
B(CreateBlockContext), U8(0), B(CreateBlockContext), U8(0),
B(PushContext), R(2), B(PushContext), R(1),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(6), B(Star), R(5),
B(CreateClosure), U8(2), U8(0), U8(2), B(CreateClosure), U8(2), U8(0), U8(2),
B(Star), R(3), B(Star), R(2),
B(LdaConstant), U8(1), 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(Star), R(4), B(Star), R(4),
B(Mov), R(3), R(5), B(CreateClosure), U8(4), U8(2), U8(2),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(3),
B(Star), R(4),
B(Mov), R(5), R(1),
B(LdaConstant), U8(3),
B(Star), R(5), B(Star), R(5),
B(CallRuntime), U16(Runtime::kCreatePrivateNameSymbol), R(5), U8(1), B(CallRuntime), U16(Runtime::kCreatePrivateAccessors), R(4), U8(2),
B(StaCurrentContextSlot), U8(5),
B(CreateClosure), U8(4), U8(1), U8(2),
B(Star), R(6),
B(CreateClosure), U8(5), U8(2), U8(2),
B(Star), R(7),
B(CallRuntime), U16(Runtime::kCreatePrivateAccessors), R(6), U8(2),
B(StaCurrentContextSlot), U8(4), B(StaCurrentContextSlot), U8(4),
B(PopContext), R(2), B(PopContext), R(1),
B(Mov), R(1), R(0), B(Mov), R(2), R(0),
B(LdaUndefined), B(LdaUndefined),
/* 115 S> */ B(Return), /* 115 S> */ B(Return),
] ]
...@@ -197,7 +174,6 @@ constant pool: [ ...@@ -197,7 +174,6 @@ constant pool: [
SCOPE_INFO_TYPE, SCOPE_INFO_TYPE,
FIXED_ARRAY_TYPE, FIXED_ARRAY_TYPE,
SHARED_FUNCTION_INFO_TYPE, SHARED_FUNCTION_INFO_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["A"],
SHARED_FUNCTION_INFO_TYPE, SHARED_FUNCTION_INFO_TYPE,
SHARED_FUNCTION_INFO_TYPE, SHARED_FUNCTION_INFO_TYPE,
] ]
...@@ -213,33 +189,32 @@ snippet: " ...@@ -213,33 +189,32 @@ snippet: "
} }
} }
" "
frame size: 7 frame size: 6
parameter count: 1 parameter count: 1
bytecode array length: 61 bytecode array length: 58
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
B(CreateBlockContext), U8(0), B(CreateBlockContext), U8(0),
B(PushContext), R(2), B(PushContext), R(1),
B(LdaTheHole), B(LdaTheHole),
B(Star), R(6), B(Star), R(5),
B(CreateClosure), U8(2), U8(0), U8(2), B(CreateClosure), U8(2), U8(0), U8(2),
B(Star), R(3), B(Star), R(2),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(4), B(Star), R(3),
B(CreateClosure), U8(3), U8(1), U8(2), B(CreateClosure), U8(3), U8(1), U8(2),
B(StaCurrentContextSlot), U8(4), B(StaCurrentContextSlot), U8(4),
B(CreateClosure), U8(4), U8(2), U8(2), B(CreateClosure), U8(4), U8(2), U8(2),
B(StaCurrentContextSlot), U8(5), B(StaCurrentContextSlot), U8(5),
B(Mov), R(3), R(5), B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(3), B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(3),
B(Star), R(4), B(Star), R(3),
B(Mov), R(5), R(1),
B(LdaConstant), U8(5), B(LdaConstant), U8(5),
B(Star), R(5), B(Star), R(4),
B(CallRuntime), U16(Runtime::kCreatePrivateNameSymbol), R(5), U8(1), B(CallRuntime), U16(Runtime::kCreatePrivateNameSymbol), R(4), U8(1),
B(StaCurrentContextSlot), U8(6), B(StaCurrentContextSlot), U8(6),
B(PopContext), R(2), B(PopContext), R(1),
B(Mov), R(1), R(0), B(Mov), R(2), R(0),
B(LdaUndefined), B(LdaUndefined),
/* 87 S> */ B(Return), /* 87 S> */ B(Return),
] ]
......
...@@ -2928,6 +2928,86 @@ TEST(StaticPrivateMethodDeclaration) { ...@@ -2928,6 +2928,86 @@ TEST(StaticPrivateMethodDeclaration) {
i::FLAG_harmony_private_methods = old_methods_flag; i::FLAG_harmony_private_methods = old_methods_flag;
} }
TEST(StaticPrivateMethodAccess) {
bool old_methods_flag = i::FLAG_harmony_private_methods;
i::FLAG_harmony_private_methods = true;
InitializedIgnitionHandleScope scope;
BytecodeExpectationsPrinter printer(CcTest::isolate());
printer.set_wrap(false);
printer.set_test_function_name("test");
const char* snippets[] = {
"class A {\n"
" static #a() { return 1; }\n"
" static test() { return this.#a(); }\n"
"}\n"
"\n"
"var test = A.test;\n"
"test();\n",
"class B {\n"
" static #b() { return 1; }\n"
" static test() { this.#b = 1; }\n"
"}\n"
"\n"
"var test = B.test;\n"
"test();\n",
"class C {\n"
" static #c() { return 1; }\n"
" static test() { this.#c++; }\n"
"}\n"
"\n"
"var test = C.test;\n"
"test();\n",
"class D {\n"
" static get #d() { return 1; }\n"
" static set #d(val) { }\n"
"\n"
" static test() {\n"
" this.#d++;\n"
" this.#d = 1;\n"
" return this.#d;\n"
" }\n"
"}\n"
"\n"
"var test = D.test;\n"
"test();\n",
"class E {\n"
" static get #e() { return 1; }\n"
" static test() { this.#e++; }\n"
"}\n"
"var test = E.test;\n"
"test();\n",
"class F {\n"
" static set #f(val) { }\n"
" static test() { this.#f++; }\n"
"}\n"
"var test = F.test;\n"
"test();\n",
"class G {\n"
" static get #d() { return 1; }\n"
" static test() { this.#d = 1; }\n"
"}\n"
"var test = G.test;\n"
"test();\n",
"class H {\n"
" set #h(val) { }\n"
" static test() { this.#h; }\n"
"}\n"
"var test = H.test;\n"
"test();\n"};
CHECK(CompareTexts(BuildActual(printer, snippets),
LoadGolden("StaticPrivateMethodAccess.golden")));
i::FLAG_harmony_private_methods = old_methods_flag;
}
TEST(PrivateAccessorDeclaration) { TEST(PrivateAccessorDeclaration) {
bool old_methods_flag = i::FLAG_harmony_private_methods; bool old_methods_flag = i::FLAG_harmony_private_methods;
i::FLAG_harmony_private_methods = true; i::FLAG_harmony_private_methods = true;
......
...@@ -109,26 +109,6 @@ Running test: testScopesPaused ...@@ -109,26 +109,6 @@ Running test: testScopesPaused
type : local type : local
} }
[1] : { [1] : {
endLocation : {
columnNumber : 3
lineNumber : 15
scriptId : <scriptId>
}
name : run
object : {
className : Object
description : Object
objectId : <objectId>
type : object
}
startLocation : {
columnNumber : 9
lineNumber : 11
scriptId : <scriptId>
}
type : block
}
[2] : {
endLocation : { endLocation : {
columnNumber : 1 columnNumber : 1
lineNumber : 19 lineNumber : 19
...@@ -148,7 +128,7 @@ Running test: testScopesPaused ...@@ -148,7 +128,7 @@ Running test: testScopesPaused
} }
type : local type : local
} }
[3] : { [2] : {
object : { object : {
className : global className : global
description : global description : global
......
...@@ -11,7 +11,10 @@ ...@@ -11,7 +11,10 @@
let store = 1; let store = 1;
class C { class C {
static #a() { return store; } static #a() { return store; }
static a() { return this.#a(); }
} }
assertEquals(C.a(), store);
assertThrows(() => C.a.call(new C), TypeError);
} }
// Complementary static private accessors. // Complementary static private accessors.
...@@ -20,7 +23,208 @@ ...@@ -20,7 +23,208 @@
class C { class C {
static get #a() { return store; } static get #a() { return store; }
static set #a(val) { store = val; } static set #a(val) { store = val; }
static incA() { this.#a++; }
static getA() { return this.#a; }
static setA(val) { this.#a = val; }
} }
assertEquals(C.getA(), 1);
C.incA();
assertEquals(store, 2);
C.setA(3);
assertEquals(store, 3);
assertThrows(() => C.incA.call(new C), TypeError);
assertThrows(() => C.getA.call(new C), TypeError);
assertThrows(() => C.setA.call(new C), TypeError);
assertThrows(() => { const incA = C.incA; incA(); }, TypeError);
assertThrows(() => { const getA = C.getA; getA(); }, TypeError);
assertThrows(() => { const setA = C.setA; setA(); }, TypeError);
}
// Static private methods accessed explicitly in an anonymous nested class.
{
class Outer {
#a() { return 'Outer'; }
a() { return this.#a(); }
test() {
return class {
static #a() { return 'Inner'; }
static a() { return this.#a(); }
};
}
}
const obj = new Outer;
const C = obj.test();
assertEquals(C.a(), 'Inner');
assertThrows(() => obj.a.call(C), TypeError);
assertThrows(() => obj.a.call(new C), TypeError);
}
// Static private methods accessed explicitly in a named nested class.
{
class Outer {
#a() { return 'Outer'; }
a() { return this.#a(); }
test() {
return class Inner {
static #a() { return 'Inner'; }
static a() { return this.#a(); }
};
}
}
const obj = new Outer;
const C = obj.test();
assertEquals(C.a(), 'Inner');
assertThrows(() => obj.a.call(C), TypeError);
assertThrows(() => obj.a.call(new C), TypeError);
}
// Static private methods accessed through eval in an anonymous nested class.
{
class Outer {
#a() { return 'Outer'; }
a() { return this.#a(); }
test() {
return class {
static #a() { return 'Inner'; }
static a(str) { return eval(str); }
};
}
}
const obj = new Outer;
const C = obj.test();
assertEquals(C.a('this.#a()'), 'Inner');
assertThrows(() => C.a('Outer.#a()'), TypeError);
}
// Static private methods accessed through eval in a named nested class.
{
class Outer {
#a() { return 'Outer'; }
a() { return this.#a(); }
test() {
return class Inner {
static #a() { return 'Inner'; }
static a(str) { return eval(str); }
};
}
}
const obj = new Outer;
const C = obj.test();
assertEquals(C.a('this.#a()'), 'Inner');
assertEquals(C.a('Inner.#a()'), 'Inner');
assertThrows(() => C.a('Outer.#a()'), TypeError);
assertThrows(() => C.run('(new Outer).#a()'), TypeError);
}
// Static private methods in the outer class accessed through eval
// in a named nested class.
{
class Outer {
static #a() { return 'Outer'; }
static test() {
return class Inner {
static run(str) { return eval(str); }
};
}
}
const C = Outer.test();
assertEquals(C.run('Outer.#a()'), 'Outer');
assertThrows(() => C.run('this.#a()'), TypeError);
assertThrows(() => C.run('Inner.#a()'), TypeError);
assertThrows(() => C.run('(new Outer).#a()'), TypeError);
}
// Static private methods in the outer class accessed explicitly
// in a named nested class.
{
class Outer {
static #a() { return 'Outer'; }
static test() {
return class Inner {
static getA(klass) { return klass.#a(); }
};
}
}
const C = Outer.test();
assertEquals(C.getA(Outer), 'Outer');
assertThrows(() => C.getA.call(C), TypeError);
assertThrows(() => C.getA.call(new Outer), TypeError);
}
// Static private methods in the outer class accessed explicitly
// in an anonymous nested class.
{
class Outer {
static #a() { return 'Outer'; }
static test() {
return class {
static getA(klass) { return klass.#a(); }
};
}
}
const C = Outer.test();
assertEquals(C.getA(Outer), 'Outer');
assertThrows(() => C.getA.call(C), TypeError);
assertThrows(() => C.getA.call(new Outer), TypeError);
}
// Super property access in static private methods
{
class A {
static a = 1;
}
class B extends A {
static #a() { return super.a; }
static getA() { return this.#a(); }
}
assertEquals(B.getA(), 1);
}
// Invalid super property access in static private methods
{
class A {
static #a() { return 1; }
static getA() { return this.#a(); }
}
class B extends A {
static getA() { return super.getA(); }
}
assertThrows(() => B.getA(), TypeError);
}
// Static private methods accessed in eval.
{
class C {
static #m(v) { return v; }
static test(str) {
return eval(str);
}
}
assertEquals(C.test('this.#m(1)'), 1);
}
// Test that the receiver is checked during run time.
{
const C = class {
static #a() { }
static test(klass) { return klass.#a; }
};
const test = C.test;
assertThrows(test, TypeError);
} }
// Duplicate static private accessors and methods. // Duplicate static private accessors and methods.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment