Commit c2bcfc31 authored by bakkot's avatar bakkot Committed by Commit bot

Wrap ClassLiterals in DoExpressions instead of giving them BlockScopes.

This slightly simplifies scope handling. It also makes it possible to
implement some potential future changes to classes purely in the parser
by adding additional code to the DoExpression.

This is a portion of https://codereview.chromium.org/2142333002/, which
probably isn't going through in full.

Review-Url: https://codereview.chromium.org/2176653003
Cr-Commit-Position: refs/heads/master@{#38035}
parent a4bd96a6
......@@ -141,8 +141,8 @@ bool Expression::IsValidReferenceExpressionOrThis() const {
bool Expression::IsAnonymousFunctionDefinition() const {
return (IsFunctionLiteral() &&
AsFunctionLiteral()->IsAnonymousFunctionDefinition()) ||
(IsClassLiteral() &&
AsClassLiteral()->IsAnonymousFunctionDefinition());
(IsDoExpression() &&
AsDoExpression()->IsAnonymousFunctionDefinition());
}
void Expression::MarkTail() {
......@@ -155,6 +155,12 @@ void Expression::MarkTail() {
}
}
bool DoExpression::IsAnonymousFunctionDefinition() const {
// This is specifically to allow DoExpressions to represent ClassLiterals.
return represented_function_ != nullptr &&
represented_function_->raw_name()->length() == 0;
}
bool Statement::IsJump() const {
switch (node_type()) {
#define JUMP_NODE_LIST(V) \
......
......@@ -474,10 +474,18 @@ class DoExpression final : public Expression {
void set_block(Block* b) { block_ = b; }
VariableProxy* result() { return result_; }
void set_result(VariableProxy* v) { result_ = v; }
FunctionLiteral* represented_function() { return represented_function_; }
void set_represented_function(FunctionLiteral* f) {
represented_function_ = f;
}
bool IsAnonymousFunctionDefinition() const;
protected:
DoExpression(Zone* zone, Block* block, VariableProxy* result, int pos)
: Expression(zone, pos, kDoExpression), block_(block), result_(result) {
: Expression(zone, pos, kDoExpression),
block_(block),
result_(result),
represented_function_(nullptr) {
DCHECK_NOT_NULL(block_);
DCHECK_NOT_NULL(result_);
}
......@@ -488,6 +496,7 @@ class DoExpression final : public Expression {
Block* block_;
VariableProxy* result_;
FunctionLiteral* represented_function_;
};
......@@ -2715,7 +2724,6 @@ class ClassLiteral final : public Expression {
DECLARE_NODE_TYPE(ClassLiteral)
Scope* scope() const { return scope_; }
VariableProxy* class_variable_proxy() const { return class_variable_proxy_; }
Expression* extends() const { return extends_; }
void set_extends(Expression* e) { extends_ = e; }
......@@ -2725,18 +2733,15 @@ class ClassLiteral final : public Expression {
int start_position() const { return position(); }
int end_position() const { return end_position_; }
BailoutId EntryId() const { return BailoutId(local_id(0)); }
BailoutId DeclsId() const { return BailoutId(local_id(1)); }
BailoutId ExitId() { return BailoutId(local_id(2)); }
BailoutId CreateLiteralId() const { return BailoutId(local_id(3)); }
BailoutId PrototypeId() { return BailoutId(local_id(4)); }
BailoutId CreateLiteralId() const { return BailoutId(local_id(0)); }
BailoutId PrototypeId() { return BailoutId(local_id(1)); }
// Return an AST id for a property that is used in simulate instructions.
BailoutId GetIdForProperty(int i) { return BailoutId(local_id(i + 5)); }
BailoutId GetIdForProperty(int i) { return BailoutId(local_id(i + 2)); }
// Unlike other AST nodes, this number of bailout IDs allocated for an
// ClassLiteral can vary, so num_ids() is not a static method.
int num_ids() const { return parent_num_ids() + 5 + properties()->length(); }
int num_ids() const { return parent_num_ids() + 2 + properties()->length(); }
// Object literals need one feedback slot for each non-trivial value, as well
// as some slots for home objects.
......@@ -2751,18 +2756,14 @@ class ClassLiteral final : public Expression {
FeedbackVectorSlot PrototypeSlot() const { return prototype_slot_; }
FeedbackVectorSlot ProxySlot() const { return proxy_slot_; }
bool IsAnonymousFunctionDefinition() const {
return constructor()->raw_name()->length() == 0;
}
protected:
ClassLiteral(Zone* zone, Scope* scope, VariableProxy* class_variable_proxy,
ClassLiteral(Zone* zone, VariableProxy* class_variable_proxy,
Expression* extends, FunctionLiteral* constructor,
ZoneList<Property*>* properties, int start_position,
int end_position)
: Expression(zone, start_position, kClassLiteral),
end_position_(end_position),
scope_(scope),
class_variable_proxy_(class_variable_proxy),
extends_(extends),
constructor_(constructor),
......@@ -2776,7 +2777,6 @@ class ClassLiteral final : public Expression {
int end_position_;
FeedbackVectorSlot prototype_slot_;
FeedbackVectorSlot proxy_slot_;
Scope* scope_;
VariableProxy* class_variable_proxy_;
Expression* extends_;
FunctionLiteral* constructor_;
......@@ -3425,14 +3425,13 @@ class AstNodeFactory final BASE_EMBEDDED {
false);
}
ClassLiteral* NewClassLiteral(Scope* scope, VariableProxy* proxy,
Expression* extends,
ClassLiteral* NewClassLiteral(VariableProxy* proxy, Expression* extends,
FunctionLiteral* constructor,
ZoneList<ObjectLiteral::Property*>* properties,
int start_position, int end_position) {
return new (local_zone_)
ClassLiteral(local_zone_, scope, proxy, extends, constructor,
properties, start_position, end_position);
ClassLiteral(local_zone_, proxy, extends, constructor, properties,
start_position, end_position);
}
NativeFunctionLiteral* NewNativeFunctionLiteral(const AstRawString* name,
......
......@@ -1635,20 +1635,6 @@ void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) {
// Visit declarations and class literal in a block scope.
if (expr->scope()->ContextLocalCount() > 0) {
Node* context = BuildLocalBlockContext(expr->scope());
ContextScope scope(this, expr->scope(), context);
VisitDeclarations(expr->scope()->declarations());
VisitClassLiteralContents(expr);
} else {
VisitDeclarations(expr->scope()->declarations());
VisitClassLiteralContents(expr);
}
}
void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
VisitForValueOrTheHole(expr->extends());
VisitForValue(expr->constructor());
......
......@@ -457,9 +457,6 @@ class AstGraphBuilder : public AstVisitor<AstGraphBuilder> {
void VisitObjectLiteralAccessor(Node* home_object,
ObjectLiteralProperty* property);
// Dispatched from VisitClassLiteral.
void VisitClassLiteralContents(ClassLiteral* expr);
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
DISALLOW_COPY_AND_ASSIGN(AstGraphBuilder);
};
......
......@@ -1446,45 +1446,38 @@ void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) {
Comment cmnt(masm_, "[ ClassLiteral");
{
NestedClassLiteral nested_class_literal(this, lit);
EnterBlockScopeIfNeeded block_scope_state(
this, lit->scope(), lit->EntryId(), lit->DeclsId(), lit->ExitId());
if (lit->extends() != NULL) {
VisitForStackValue(lit->extends());
} else {
PushOperand(isolate()->factory()->the_hole_value());
}
if (lit->extends() != NULL) {
VisitForStackValue(lit->extends());
} else {
PushOperand(isolate()->factory()->the_hole_value());
}
VisitForStackValue(lit->constructor());
VisitForStackValue(lit->constructor());
PushOperand(Smi::FromInt(lit->start_position()));
PushOperand(Smi::FromInt(lit->end_position()));
PushOperand(Smi::FromInt(lit->start_position()));
PushOperand(Smi::FromInt(lit->end_position()));
CallRuntimeWithOperands(Runtime::kDefineClass);
PrepareForBailoutForId(lit->CreateLiteralId(), BailoutState::TOS_REGISTER);
PushOperand(result_register());
CallRuntimeWithOperands(Runtime::kDefineClass);
PrepareForBailoutForId(lit->CreateLiteralId(), BailoutState::TOS_REGISTER);
PushOperand(result_register());
// Load the "prototype" from the constructor.
__ Move(LoadDescriptor::ReceiverRegister(), result_register());
__ LoadRoot(LoadDescriptor::NameRegister(),
Heap::kprototype_stringRootIndex);
__ Move(LoadDescriptor::SlotRegister(), SmiFromSlot(lit->PrototypeSlot()));
CallLoadIC();
PrepareForBailoutForId(lit->PrototypeId(), BailoutState::TOS_REGISTER);
PushOperand(result_register());
// Load the "prototype" from the constructor.
__ Move(LoadDescriptor::ReceiverRegister(), result_register());
__ LoadRoot(LoadDescriptor::NameRegister(), Heap::kprototype_stringRootIndex);
__ Move(LoadDescriptor::SlotRegister(), SmiFromSlot(lit->PrototypeSlot()));
CallLoadIC();
PrepareForBailoutForId(lit->PrototypeId(), BailoutState::TOS_REGISTER);
PushOperand(result_register());
EmitClassDefineProperties(lit);
DropOperands(1);
EmitClassDefineProperties(lit);
DropOperands(1);
// Set the constructor to have fast properties.
CallRuntimeWithOperands(Runtime::kToFastProperties);
// Set the constructor to have fast properties.
CallRuntimeWithOperands(Runtime::kToFastProperties);
if (lit->class_variable_proxy() != nullptr) {
EmitVariableAssignment(lit->class_variable_proxy()->var(), Token::INIT,
lit->ProxySlot());
}
if (lit->class_variable_proxy() != nullptr) {
EmitVariableAssignment(lit->class_variable_proxy()->var(), Token::INIT,
lit->ProxySlot());
}
context()->Plug(result_register());
......
......@@ -201,23 +201,6 @@ class FullCodeGenerator final : public AstVisitor<FullCodeGenerator> {
}
};
// A class literal expression
class NestedClassLiteral : public NestedStatement {
public:
NestedClassLiteral(FullCodeGenerator* codegen, ClassLiteral* lit)
: NestedStatement(codegen),
needs_context_(lit->scope() != nullptr &&
lit->scope()->NeedsContext()) {}
NestedStatement* Exit(int* context_length) override {
if (needs_context_) ++(*context_length);
return previous_;
}
private:
const bool needs_context_;
};
class DeferredCommands {
public:
enum Command { kReturn, kThrow, kBreak, kContinue };
......
......@@ -1361,18 +1361,6 @@ void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
}
void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
if (expr->scope()->ContextLocalCount() > 0) {
VisitNewLocalBlockContext(expr->scope());
ContextScope scope(this, expr->scope());
VisitDeclarations(expr->scope()->declarations());
VisitClassLiteralContents(expr);
} else {
VisitDeclarations(expr->scope()->declarations());
VisitClassLiteralContents(expr);
}
}
void BytecodeGenerator::VisitClassLiteralContents(ClassLiteral* expr) {
VisitClassLiteralForRuntimeDefinition(expr);
// Load the "prototype" from the constructor.
......
......@@ -127,7 +127,6 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
void VisitArgumentsObject(Variable* variable);
void VisitRestArgumentsArray(Variable* rest);
void VisitCallSuper(Call* call);
void VisitClassLiteralContents(ClassLiteral* expr);
void VisitClassLiteralForRuntimeDefinition(ClassLiteral* expr);
void VisitClassLiteralProperties(ClassLiteral* expr, Register literal,
Register prototype);
......
......@@ -42,7 +42,6 @@ void Rewriter::VisitFunctionLiteral(FunctionLiteral* function_literal) {
void Rewriter::VisitClassLiteral(ClassLiteral* class_literal) {
class_literal->scope()->ReplaceOuterScope(param_scope_);
if (class_literal->extends() != nullptr) {
Visit(class_literal->extends());
}
......
......@@ -796,7 +796,7 @@ FunctionLiteral* ParserTraits::ParseFunctionLiteral(
function_token_position, type, language_mode, ok);
}
ClassLiteral* ParserTraits::ParseClassLiteral(
Expression* ParserTraits::ParseClassLiteral(
Type::ExpressionClassifier* classifier, const AstRawString* name,
Scanner::Location class_name_location, bool name_is_strict_reserved,
int pos, bool* ok) {
......@@ -2267,8 +2267,8 @@ Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names,
variable_name = name;
}
ClassLiteral* value = ParseClassLiteral(nullptr, name, scanner()->location(),
is_strict_reserved, pos, CHECK_OK);
Expression* value = ParseClassLiteral(nullptr, name, scanner()->location(),
is_strict_reserved, pos, CHECK_OK);
VariableProxy* proxy = NewUnresolved(variable_name, LET);
Declaration* declaration =
......@@ -5005,11 +5005,11 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
return result;
}
ClassLiteral* Parser::ParseClassLiteral(ExpressionClassifier* classifier,
const AstRawString* name,
Scanner::Location class_name_location,
bool name_is_strict_reserved, int pos,
bool* ok) {
Expression* Parser::ParseClassLiteral(ExpressionClassifier* classifier,
const AstRawString* name,
Scanner::Location class_name_location,
bool name_is_strict_reserved, int pos,
bool* ok) {
// All parts of a ClassDeclaration and ClassExpression are strict code.
if (name_is_strict_reserved) {
ReportMessageAt(class_name_location,
......@@ -5111,8 +5111,21 @@ ClassLiteral* Parser::ParseClassLiteral(ExpressionClassifier* classifier,
proxy->var()->set_initializer_position(end_pos);
}
return factory()->NewClassLiteral(block_scope, proxy, extends, constructor,
properties, pos, end_pos);
Block* do_block = factory()->NewBlock(nullptr, 1, false, pos);
do_block->set_scope(block_scope);
Variable* result_var =
block_scope->NewTemporary(ast_value_factory()->empty_string());
DoExpression* do_expr = factory()->NewDoExpression(do_block, result_var, pos);
ClassLiteral* class_literal = factory()->NewClassLiteral(
proxy, extends, constructor, properties, pos, end_pos);
do_block->statements()->Add(
factory()->NewExpressionStatement(class_literal, pos), zone());
do_expr->set_represented_function(constructor);
Rewriter::Rewrite(this, do_expr, ast_value_factory());
return do_expr;
}
......@@ -6106,8 +6119,8 @@ void ParserTraits::SetFunctionName(Expression* value,
if (function != nullptr) {
function->set_raw_name(name);
} else {
DCHECK(value->IsClassLiteral());
value->AsClassLiteral()->constructor()->set_raw_name(name);
DCHECK(value->IsDoExpression());
value->AsDoExpression()->represented_function()->set_raw_name(name);
}
}
......
......@@ -582,11 +582,11 @@ class ParserTraits {
const ParserFormalParameters& parameters, FunctionKind kind,
FunctionLiteral::FunctionType function_type, bool* ok);
ClassLiteral* ParseClassLiteral(Type::ExpressionClassifier* classifier,
const AstRawString* name,
Scanner::Location class_name_location,
bool name_is_strict_reserved, int pos,
bool* ok);
Expression* ParseClassLiteral(Type::ExpressionClassifier* classifier,
const AstRawString* name,
Scanner::Location class_name_location,
bool name_is_strict_reserved, int pos,
bool* ok);
V8_INLINE void MarkCollectedTailCallExpressions();
V8_INLINE void MarkTailPosition(Expression* expression);
......@@ -1002,11 +1002,11 @@ class Parser : public ParserBase<ParserTraits> {
int function_token_position, FunctionLiteral::FunctionType type,
LanguageMode language_mode, bool* ok);
ClassLiteral* ParseClassLiteral(ExpressionClassifier* classifier,
const AstRawString* name,
Scanner::Location class_name_location,
bool name_is_strict_reserved, int pos,
bool* ok);
Expression* ParseClassLiteral(ExpressionClassifier* classifier,
const AstRawString* name,
Scanner::Location class_name_location,
bool name_is_strict_reserved, int pos,
bool* ok);
// Magical syntax support.
Expression* ParseV8Intrinsic(bool* ok);
......
......@@ -14,39 +14,40 @@ snippet: "
speak() { console.log(this.name + ' is speaking.'); }
}
"
frame size: 9
frame size: 10
parameter count: 1
bytecode array length: 72
bytecode array length: 74
bytecodes: [
B(LdaTheHole),
B(Star), R(1),
B(Star), R(2),
/* 30 E> */ B(StackCheck),
B(LdaTheHole),
B(Star), R(0),
B(LdaTheHole),
B(Star), R(2),
B(CreateClosure), U8(0), U8(2),
/* 34 S> */ B(LdaTheHole),
B(Star), R(3),
B(LdaSmi), U8(34),
B(CreateClosure), U8(0), U8(2),
B(Star), R(4),
B(Wide), B(LdaSmi), U16(148),
B(LdaSmi), U8(34),
B(Star), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(2), U8(4),
B(Star), R(2),
B(LdrNamedProperty), R(2), U8(1), U8(1), R(3),
B(Wide), B(LdaSmi), U16(148),
B(Star), R(6),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
B(Star), R(3),
B(LdrNamedProperty), R(3), U8(1), U8(1), R(4),
B(LdaConstant), U8(2),
B(Star), R(5),
B(CreateClosure), U8(3), U8(2),
B(Star), R(6),
B(LdaSmi), U8(2),
B(CreateClosure), U8(3), U8(2),
B(Star), R(7),
B(LdaZero),
B(LdaSmi), U8(2),
B(Star), R(8),
B(Mov), R(3), R(4),
B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(4), U8(5),
B(CallRuntime), U16(Runtime::kToFastProperties), R(2), U8(1),
B(LdaZero),
B(Star), R(9),
B(Mov), R(4), R(5),
B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(5), U8(5),
B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1),
B(Star), R(0),
B(Star), R(1),
B(Star), R(2),
B(LdaUndefined),
/* 149 S> */ B(Return),
]
......@@ -66,39 +67,40 @@ snippet: "
speak() { console.log(this.name + ' is speaking.'); }
}
"
frame size: 9
frame size: 10
parameter count: 1
bytecode array length: 72
bytecode array length: 74
bytecodes: [
B(LdaTheHole),
B(Star), R(1),
B(Star), R(2),
/* 30 E> */ B(StackCheck),
B(LdaTheHole),
B(Star), R(0),
B(LdaTheHole),
B(Star), R(2),
B(CreateClosure), U8(0), U8(2),
/* 34 S> */ B(LdaTheHole),
B(Star), R(3),
B(LdaSmi), U8(34),
B(CreateClosure), U8(0), U8(2),
B(Star), R(4),
B(Wide), B(LdaSmi), U16(148),
B(LdaSmi), U8(34),
B(Star), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(2), U8(4),
B(Star), R(2),
B(LdrNamedProperty), R(2), U8(1), U8(1), R(3),
B(Wide), B(LdaSmi), U16(148),
B(Star), R(6),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
B(Star), R(3),
B(LdrNamedProperty), R(3), U8(1), U8(1), R(4),
B(LdaConstant), U8(2),
B(Star), R(5),
B(CreateClosure), U8(3), U8(2),
B(Star), R(6),
B(LdaSmi), U8(2),
B(CreateClosure), U8(3), U8(2),
B(Star), R(7),
B(LdaZero),
B(LdaSmi), U8(2),
B(Star), R(8),
B(Mov), R(3), R(4),
B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(4), U8(5),
B(CallRuntime), U16(Runtime::kToFastProperties), R(2), U8(1),
B(LdaZero),
B(Star), R(9),
B(Mov), R(4), R(5),
B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(5), U8(5),
B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1),
B(Star), R(0),
B(Star), R(1),
B(Star), R(2),
B(LdaUndefined),
/* 149 S> */ B(Return),
]
......@@ -120,14 +122,14 @@ snippet: "
static [n1]() { return n1; }
}
"
frame size: 10
frame size: 11
parameter count: 1
bytecode array length: 124
bytecode array length: 126
bytecodes: [
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
B(PushContext), R(2),
B(PushContext), R(3),
B(LdaTheHole),
B(Star), R(1),
B(Star), R(2),
/* 30 E> */ B(StackCheck),
/* 43 S> */ B(LdaConstant), U8(0),
/* 43 E> */ B(StaContextSlot), R(context), U8(4),
......@@ -135,42 +137,43 @@ bytecodes: [
/* 57 E> */ B(StaContextSlot), R(context), U8(5),
B(LdaTheHole),
B(Star), R(0),
B(LdaTheHole),
B(Star), R(3),
B(CreateClosure), U8(2), U8(2),
/* 62 S> */ B(LdaTheHole),
B(Star), R(4),
B(LdaSmi), U8(62),
B(CreateClosure), U8(2), U8(2),
B(Star), R(5),
B(Wide), B(LdaSmi), U16(128),
B(LdaSmi), U8(62),
B(Star), R(6),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
B(Star), R(3),
B(LdrNamedProperty), R(3), U8(3), U8(1), R(4),
B(Wide), B(LdaSmi), U16(128),
B(Star), R(7),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4),
B(Star), R(4),
B(LdrNamedProperty), R(4), U8(3), U8(1), R(5),
/* 75 E> */ B(LdaContextSlot), R(context), U8(4),
B(ToName), R(6),
B(ToName), R(7),
B(CreateClosure), U8(4), U8(2),
B(Star), R(7),
B(LdaSmi), U8(2),
B(Star), R(8),
B(LdaSmi), U8(1),
B(LdaSmi), U8(2),
B(Star), R(9),
B(Mov), R(4), R(5),
B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(5), U8(5),
B(LdaSmi), U8(1),
B(Star), R(10),
B(Mov), R(5), R(6),
B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(6), U8(5),
/* 106 E> */ B(LdaContextSlot), R(context), U8(5),
B(ToName), R(6),
B(ToName), R(7),
B(LdaConstant), U8(3),
B(TestEqualStrict), R(6),
B(Mov), R(3), R(5),
B(TestEqualStrict), R(7),
B(Mov), R(4), R(6),
B(JumpIfToBooleanFalse), U8(7),
B(CallRuntime), U16(Runtime::kThrowStaticPrototypeError), R(0), U8(0),
B(CreateClosure), U8(5), U8(2),
B(Star), R(7),
B(Star), R(8),
B(LdaSmi), U8(1),
B(Star), R(9),
B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(5), U8(5),
B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1),
B(Star), R(10),
B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(6), U8(5),
B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1),
B(Star), R(0),
B(Star), R(1),
B(Star), R(2),
B(LdaUndefined),
/* 129 S> */ B(Return),
]
......@@ -191,39 +194,40 @@ snippet: "
class C { constructor() { count++; }}
return new C();
"
frame size: 7
frame size: 8
parameter count: 1
bytecode array length: 73
bytecode array length: 75
bytecodes: [
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
B(PushContext), R(2),
B(PushContext), R(3),
B(LdaTheHole),
B(Star), R(1),
B(Star), R(2),
/* 30 E> */ B(StackCheck),
/* 46 S> */ B(LdaZero),
/* 46 E> */ B(StaContextSlot), R(context), U8(4),
B(LdaTheHole),
B(Star), R(0),
B(LdaTheHole),
B(Star), R(3),
B(CreateClosure), U8(0), U8(2),
/* 49 S> */ B(LdaTheHole),
B(Star), R(4),
B(LdaSmi), U8(49),
B(CreateClosure), U8(0), U8(2),
B(Star), R(5),
B(LdaSmi), U8(86),
B(LdaSmi), U8(49),
B(Star), R(6),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
B(Star), R(3),
B(LdrNamedProperty), R(3), U8(1), U8(1), R(4),
B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1),
B(LdaSmi), U8(86),
B(Star), R(7),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4),
B(Star), R(4),
B(LdrNamedProperty), R(4), U8(1), U8(1), R(5),
B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1),
B(Star), R(0),
B(Star), R(1),
B(Star), R(2),
/* 87 S> */ B(JumpIfNotHole), U8(11),
B(LdaConstant), U8(2),
B(Star), R(5),
B(CallRuntime), U16(Runtime::kThrowReferenceError), R(5), U8(1),
B(Star), R(4),
B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1),
B(Star), R(3),
/* 94 E> */ B(New), R(3), R(0), U8(0),
/* 94 E> */ B(New), R(4), R(0), U8(0),
/* 103 S> */ B(Return),
]
constant pool: [
......
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