[es6] don't use do-expressions to desugar ES6 classes

Removes the do-expression wrapping, modifies BytecodeGenerator change
to enter a class literal's block scope if needed.

This does not solve the actual bug in v8:6322, but helps mitigate it in
simple cases. The bug is caused by BytecodeGenerator not allocating a
large enough array of context registers to hold its entire stack,
allowing non-context registers to be overwritten during PushContext and
PopContext bytecodes.

Nevertheless, I like the idea of not depending on do-expressions when
possible, so I think it's worth doing anyways.

BUG=v8:6322
R=rmcilroy@chromium.org, marja@chromium.org, littledan@chromium.org

Change-Id: I82b7569db2a0eead1694bd04765fc4456c2f1a0a
Reviewed-on: https://chromium-review.googlesource.com/491074
Commit-Queue: Caitlin Potter <caitp@igalia.com>
Reviewed-by: Marja Hölttä <marja@chromium.org>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: Daniel Ehrenberg <littledan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45110}
This commit is contained in:
Caitlin Potter 2017-05-04 13:00:44 -04:00 committed by Commit Bot
parent 5228af67e1
commit c6540ab1b7
15 changed files with 278 additions and 268 deletions

View File

@ -563,6 +563,7 @@ void AstNumberingVisitor::VisitClassLiteral(ClassLiteral* node) {
IncrementNodeCount();
DisableFullCodegenAndCrankshaft(kClassLiteral);
node->set_base_id(ReserveIdRange(ClassLiteral::num_ids()));
LanguageModeScope language_mode_scope(this, STRICT);
if (node->extends()) Visit(node->extends());
if (node->constructor()) Visit(node->constructor());
if (node->class_variable_proxy()) {

View File

@ -147,8 +147,8 @@ bool Expression::IsValidReferenceExpressionOrThis() const {
bool Expression::IsAnonymousFunctionDefinition() const {
return (IsFunctionLiteral() &&
AsFunctionLiteral()->IsAnonymousFunctionDefinition()) ||
(IsDoExpression() &&
AsDoExpression()->IsAnonymousFunctionDefinition());
(IsClassLiteral() &&
AsClassLiteral()->IsAnonymousFunctionDefinition());
}
void Expression::MarkTail() {
@ -161,12 +161,6 @@ void Expression::MarkTail() {
}
}
bool DoExpression::IsAnonymousFunctionDefinition() const {
// This is specifically to allow DoExpressions to represent ClassLiterals.
return represented_function_ != nullptr &&
represented_function_->raw_name()->IsEmpty();
}
bool Statement::IsJump() const {
switch (node_type()) {
#define JUMP_NODE_LIST(V) \

View File

@ -484,20 +484,12 @@ 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;
private:
friend class AstNodeFactory;
DoExpression(Block* block, VariableProxy* result, int pos)
: Expression(pos, kDoExpression),
block_(block),
result_(result),
represented_function_(nullptr) {
: Expression(pos, kDoExpression), block_(block), result_(result) {
DCHECK_NOT_NULL(block_);
DCHECK_NOT_NULL(result_);
}
@ -506,7 +498,6 @@ class DoExpression final : public Expression {
Block* block_;
VariableProxy* result_;
FunctionLiteral* represented_function_;
};
@ -2852,6 +2843,7 @@ class ClassLiteral final : public Expression {
public:
typedef ClassLiteralProperty Property;
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; }
@ -2867,6 +2859,13 @@ class ClassLiteral final : public Expression {
return HasStaticComputedNames::decode(bit_field_);
}
bool is_anonymous_expression() const {
return IsAnonymousExpression::decode(bit_field_);
}
bool IsAnonymousFunctionDefinition() const {
return is_anonymous_expression();
}
// Object literals need one feedback slot for each non-trivial value, as well
// as some slots for home objects.
void AssignFeedbackSlots(FeedbackVectorSpec* spec, LanguageMode language_mode,
@ -2883,23 +2882,27 @@ class ClassLiteral final : public Expression {
private:
friend class AstNodeFactory;
ClassLiteral(VariableProxy* class_variable_proxy, Expression* extends,
FunctionLiteral* constructor, ZoneList<Property*>* properties,
int start_position, int end_position,
bool has_name_static_property, bool has_static_computed_names)
ClassLiteral(Scope* scope, VariableProxy* class_variable_proxy,
Expression* extends, FunctionLiteral* constructor,
ZoneList<Property*>* properties, int start_position,
int end_position, bool has_name_static_property,
bool has_static_computed_names, bool is_anonymous)
: Expression(start_position, kClassLiteral),
end_position_(end_position),
scope_(scope),
class_variable_proxy_(class_variable_proxy),
extends_(extends),
constructor_(constructor),
properties_(properties) {
bit_field_ |= HasNameStaticProperty::encode(has_name_static_property) |
HasStaticComputedNames::encode(has_static_computed_names);
HasStaticComputedNames::encode(has_static_computed_names) |
IsAnonymousExpression::encode(is_anonymous);
}
int end_position_;
FeedbackSlot home_object_slot_;
FeedbackSlot proxy_slot_;
Scope* scope_;
VariableProxy* class_variable_proxy_;
Expression* extends_;
FunctionLiteral* constructor_;
@ -2909,6 +2912,8 @@ class ClassLiteral final : public Expression {
: public BitField<bool, Expression::kNextBitFieldIndex, 1> {};
class HasStaticComputedNames
: public BitField<bool, HasNameStaticProperty::kNext, 1> {};
class IsAnonymousExpression
: public BitField<bool, HasStaticComputedNames::kNext, 1> {};
};
@ -3615,15 +3620,18 @@ class AstNodeFactory final BASE_EMBEDDED {
ClassLiteral::Property(key, value, kind, is_static, is_computed_name);
}
ClassLiteral* NewClassLiteral(VariableProxy* proxy, Expression* extends,
ClassLiteral* NewClassLiteral(Scope* scope, VariableProxy* proxy,
Expression* extends,
FunctionLiteral* constructor,
ZoneList<ClassLiteral::Property*>* properties,
int start_position, int end_position,
bool has_name_static_property,
bool has_static_computed_names) {
return new (zone_) ClassLiteral(
proxy, extends, constructor, properties, start_position, end_position,
has_name_static_property, has_static_computed_names);
bool has_static_computed_names,
bool is_anonymous) {
return new (zone_)
ClassLiteral(scope, proxy, extends, constructor, properties,
start_position, end_position, has_name_static_property,
has_static_computed_names, is_anonymous);
}
NativeFunctionLiteral* NewNativeFunctionLiteral(const AstRawString* name,

View File

@ -39,9 +39,15 @@ class BytecodeGenerator::ContextScope BASE_EMBEDDED {
if (outer_) {
depth_ = outer_->depth_ + 1;
int outer_reg_index =
builder()->first_context_register().index() + outer_->depth_;
// TODO(ignition): ensure overwriting of non-context registers with
// a Context can never occurs, and re-enable DCHECK.
// DCHECK_LE(outer_reg_index, builder()->last_context_register().index());
// Push the outer context into a new context register.
Register outer_context_reg(builder()->first_context_register().index() +
outer_->depth_);
Register outer_context_reg(outer_reg_index);
outer_->set_register(outer_context_reg);
generator_->builder()->PushContext(outer_context_reg);
}
@ -1497,7 +1503,8 @@ void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
function_literals_.push_back(std::make_pair(expr, entry));
}
void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
void BytecodeGenerator::BuildClassLiteral(ClassLiteral* expr) {
VisitDeclarations(expr->scope()->declarations());
Register constructor = VisitForRegisterValue(expr->constructor());
{
RegisterAllocationScope register_scope(this);
@ -1534,6 +1541,18 @@ void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
}
}
void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
CurrentScope current_scope(this, expr->scope());
DCHECK_NOT_NULL(expr->scope());
if (expr->scope()->NeedsContext()) {
BuildNewLocalBlockContext(expr->scope());
ContextScope scope(this, expr->scope());
BuildClassLiteral(expr);
} else {
BuildClassLiteral(expr);
}
}
void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr,
Register constructor,
Register prototype) {

View File

@ -141,6 +141,7 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
void VisitClassLiteralProperties(ClassLiteral* expr, Register constructor,
Register prototype);
void BuildClassLiteralNameProperty(ClassLiteral* expr, Register constructor);
void BuildClassLiteral(ClassLiteral* expr);
void VisitThisFunctionVariable(Variable* variable);
void VisitNewTargetVariable(Variable* variable);
void VisitBlockDeclarationsAndStatements(Block* stmt);

View File

@ -631,7 +631,8 @@ class ParserBase {
constructor(parser->impl()->EmptyFunctionLiteral()),
has_seen_constructor(false),
has_name_static_property(false),
has_static_computed_names(false) {}
has_static_computed_names(false),
is_anonymous(false) {}
VariableProxy* proxy;
ExpressionT extends;
typename Types::ClassPropertyList properties;
@ -639,6 +640,7 @@ class ParserBase {
bool has_seen_constructor;
bool has_name_static_property;
bool has_static_computed_names;
bool is_anonymous;
};
DeclarationScope* NewScriptScope() const {
@ -4390,24 +4392,30 @@ template <typename Impl>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
IdentifierT name, Scanner::Location class_name_location,
bool name_is_strict_reserved, int class_token_pos, bool* ok) {
bool is_anonymous = impl()->IsEmptyIdentifier(name);
// All parts of a ClassDeclaration and ClassExpression are strict code.
if (name_is_strict_reserved) {
impl()->ReportMessageAt(class_name_location,
MessageTemplate::kUnexpectedStrictReserved);
*ok = false;
return impl()->EmptyExpression();
}
if (impl()->IsEvalOrArguments(name)) {
impl()->ReportMessageAt(class_name_location,
MessageTemplate::kStrictEvalArguments);
*ok = false;
return impl()->EmptyExpression();
if (!is_anonymous) {
if (name_is_strict_reserved) {
impl()->ReportMessageAt(class_name_location,
MessageTemplate::kUnexpectedStrictReserved);
*ok = false;
return impl()->EmptyExpression();
}
if (impl()->IsEvalOrArguments(name)) {
impl()->ReportMessageAt(class_name_location,
MessageTemplate::kStrictEvalArguments);
*ok = false;
return impl()->EmptyExpression();
}
}
BlockState block_state(zone(), &scope_);
Scope* block_scope = NewScope(BLOCK_SCOPE);
BlockState block_state(&scope_, block_scope);
RaiseLanguageMode(STRICT);
ClassInfo class_info(this);
class_info.is_anonymous = is_anonymous;
impl()->DeclareClassVariable(name, &class_info, class_token_pos, CHECK_OK);
scope()->set_start_position(scanner()->location().end_pos);
@ -4452,7 +4460,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
}
Expect(Token::RBRACE, CHECK_OK);
return impl()->RewriteClassLiteral(name, &class_info, class_token_pos, ok);
return impl()->RewriteClassLiteral(block_scope, name, &class_info,
class_token_pos, ok);
}
template <typename Impl>

View File

@ -3333,7 +3333,7 @@ void Parser::DeclareClassProperty(const AstRawString* class_name,
class_info->properties->Add(property, zone());
}
// This method rewrites a class literal into a do-expression.
// This method generates a ClassLiteral AST node.
// It uses the following fields of class_info:
// - constructor (if missing, it updates it with a default constructor)
// - proxy
@ -3341,13 +3341,14 @@ void Parser::DeclareClassProperty(const AstRawString* class_name,
// - properties
// - has_name_static_property
// - has_static_computed_names
Expression* Parser::RewriteClassLiteral(const AstRawString* name,
Expression* Parser::RewriteClassLiteral(Scope* block_scope,
const AstRawString* name,
ClassInfo* class_info, int pos,
bool* ok) {
DCHECK_NOT_NULL(block_scope);
DCHECK_EQ(block_scope->scope_type(), BLOCK_SCOPE);
DCHECK_EQ(block_scope->language_mode(), STRICT);
int end_pos = scanner()->location().end_pos;
Block* do_block = factory()->NewBlock(nullptr, 1, false, pos);
Variable* result_var = NewTemporary(ast_value_factory()->empty_string());
DoExpression* do_expr = factory()->NewDoExpression(do_block, result_var, pos);
bool has_extends = class_info->extends != nullptr;
bool has_default_constructor = class_info->constructor == nullptr;
@ -3356,7 +3357,7 @@ Expression* Parser::RewriteClassLiteral(const AstRawString* name,
DefaultConstructor(name, has_extends, pos, end_pos);
}
scope()->set_end_position(end_pos);
block_scope->set_end_position(end_pos);
if (name != nullptr) {
DCHECK_NOT_NULL(class_info->proxy);
@ -3364,23 +3365,14 @@ Expression* Parser::RewriteClassLiteral(const AstRawString* name,
}
ClassLiteral* class_literal = factory()->NewClassLiteral(
class_info->proxy, class_info->extends, class_info->constructor,
class_info->properties, pos, end_pos,
block_scope, class_info->proxy, class_info->extends,
class_info->constructor, class_info->properties, pos, end_pos,
class_info->has_name_static_property,
class_info->has_static_computed_names);
class_info->has_static_computed_names, class_info->is_anonymous);
do_block->statements()->Add(
factory()->NewExpressionStatement(
factory()->NewAssignment(Token::ASSIGN,
factory()->NewVariableProxy(result_var),
class_literal, kNoSourcePosition),
pos),
zone());
do_block->set_scope(scope()->FinalizeBlockScope());
do_expr->set_represented_function(class_info->constructor);
AddFunctionForNameInference(class_info->constructor);
return do_expr;
return class_literal;
}
Literal* Parser::GetLiteralUndefined(int position) {
@ -4270,12 +4262,11 @@ void Parser::SetFunctionName(Expression* value, const AstRawString* name) {
DCHECK_NOT_NULL(name);
if (!value->IsAnonymousFunctionDefinition()) return;
auto function = value->AsFunctionLiteral();
if (value->IsClassLiteral()) {
function = value->AsClassLiteral()->constructor();
}
if (function != nullptr) {
function->set_raw_name(ast_value_factory()->NewConsString(name));
} else {
DCHECK(value->IsDoExpression());
value->AsDoExpression()->represented_function()->set_raw_name(
ast_value_factory()->NewConsString(name));
}
}

View File

@ -373,7 +373,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
ClassLiteralProperty::Kind kind,
bool is_static, bool is_constructor,
ClassInfo* class_info, bool* ok);
V8_INLINE Expression* RewriteClassLiteral(const AstRawString* name,
V8_INLINE Expression* RewriteClassLiteral(Scope* block_scope,
const AstRawString* name,
ClassInfo* class_info, int pos,
bool* ok);
V8_INLINE Statement* DeclareNative(const AstRawString* name, int pos,

View File

@ -1134,7 +1134,8 @@ class PreParser : public ParserBase<PreParser> {
bool is_static, bool is_constructor,
ClassInfo* class_info, bool* ok) {
}
V8_INLINE PreParserExpression RewriteClassLiteral(PreParserIdentifier name,
V8_INLINE PreParserExpression RewriteClassLiteral(Scope* scope,
PreParserIdentifier name,
ClassInfo* class_info,
int pos, bool* ok) {
bool has_default_constructor = !class_info->has_seen_constructor;

View File

@ -12,39 +12,38 @@ snippet: "
speak() { console.log(this.name + ' is speaking.'); }
}
"
frame size: 9
frame size: 8
parameter count: 1
bytecode array length: 75
bytecode array length: 73
bytecodes: [
B(LdaTheHole),
B(Star), R(2),
B(Star), R(1),
/* 30 E> */ B(StackCheck),
B(LdaTheHole),
B(Star), R(0),
/* 34 S> */ B(CreateClosure), U8(0), U8(3), U8(2),
B(Star), R(3),
B(CreateClosure), U8(0), U8(3), U8(2),
B(Star), R(2),
B(LdaTheHole),
B(Star), R(4),
B(Star), R(3),
B(LdaSmi), I8(34),
B(Star), R(6),
B(Star), R(5),
B(Wide), B(LdaSmi), I16(148),
B(Star), R(7),
B(Mov), R(3), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4),
B(Star), R(4),
B(LdaConstant), U8(1),
B(Star), R(6),
B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
B(Star), R(3),
B(LdaConstant), U8(1),
B(Star), R(5),
B(CreateClosure), U8(2), U8(4), U8(2),
B(Star), R(7),
B(Star), R(6),
B(LdaSmi), I8(2),
B(Star), R(8),
B(Ldar), R(7),
B(StaDataPropertyInLiteral), R(4), R(6), U8(1), U8(5),
B(CallRuntime), U16(Runtime::kInstallClassNameAccessor), R(3), U8(1),
B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1),
B(Star), R(7),
B(Ldar), R(6),
B(StaDataPropertyInLiteral), R(3), R(5), U8(1), U8(5),
B(CallRuntime), U16(Runtime::kInstallClassNameAccessor), R(2), U8(1),
B(CallRuntime), U16(Runtime::kToFastProperties), R(2), U8(1),
B(Star), R(0),
B(Star), R(1),
B(Star), R(2),
B(LdaUndefined),
/* 149 S> */ B(Return),
]
@ -63,39 +62,38 @@ snippet: "
speak() { console.log(this.name + ' is speaking.'); }
}
"
frame size: 9
frame size: 8
parameter count: 1
bytecode array length: 75
bytecode array length: 73
bytecodes: [
B(LdaTheHole),
B(Star), R(2),
B(Star), R(1),
/* 30 E> */ B(StackCheck),
B(LdaTheHole),
B(Star), R(0),
/* 34 S> */ B(CreateClosure), U8(0), U8(3), U8(2),
B(Star), R(3),
B(CreateClosure), U8(0), U8(3), U8(2),
B(Star), R(2),
B(LdaTheHole),
B(Star), R(4),
B(Star), R(3),
B(LdaSmi), I8(34),
B(Star), R(6),
B(Star), R(5),
B(Wide), B(LdaSmi), I16(148),
B(Star), R(7),
B(Mov), R(3), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4),
B(Star), R(4),
B(LdaConstant), U8(1),
B(Star), R(6),
B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
B(Star), R(3),
B(LdaConstant), U8(1),
B(Star), R(5),
B(CreateClosure), U8(2), U8(4), U8(2),
B(Star), R(7),
B(Star), R(6),
B(LdaSmi), I8(2),
B(Star), R(8),
B(Ldar), R(7),
B(StaDataPropertyInLiteral), R(4), R(6), U8(1), U8(5),
B(CallRuntime), U16(Runtime::kInstallClassNameAccessor), R(3), U8(1),
B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1),
B(Star), R(7),
B(Ldar), R(6),
B(StaDataPropertyInLiteral), R(3), R(5), U8(1), U8(5),
B(CallRuntime), U16(Runtime::kInstallClassNameAccessor), R(2), U8(1),
B(CallRuntime), U16(Runtime::kToFastProperties), R(2), U8(1),
B(Star), R(0),
B(Star), R(1),
B(Star), R(2),
B(LdaUndefined),
/* 149 S> */ B(Return),
]
@ -116,14 +114,14 @@ snippet: "
static [n1]() { return n1; }
}
"
frame size: 10
frame size: 9
parameter count: 1
bytecode array length: 114
bytecode array length: 112
bytecodes: [
B(CreateFunctionContext), U8(2),
B(PushContext), R(3),
B(PushContext), R(2),
B(LdaTheHole),
B(Star), R(2),
B(Star), R(1),
/* 30 E> */ B(StackCheck),
/* 43 S> */ B(LdaConstant), U8(0),
/* 43 E> */ B(StaCurrentContextSlot), U8(4),
@ -131,39 +129,38 @@ bytecodes: [
/* 57 E> */ B(StaCurrentContextSlot), U8(5),
B(LdaTheHole),
B(Star), R(0),
/* 62 S> */ B(CreateClosure), U8(2), U8(3), U8(2),
B(Star), R(4),
B(CreateClosure), U8(2), U8(3), U8(2),
B(Star), R(3),
B(LdaTheHole),
B(Star), R(5),
B(Star), R(4),
B(LdaSmi), I8(62),
B(Star), R(7),
B(Star), R(6),
B(Wide), B(LdaSmi), I16(128),
B(Star), R(8),
B(Mov), R(4), R(6),
B(CallRuntime), U16(Runtime::kDefineClass), R(5), U8(4),
B(Star), R(5),
B(Star), R(7),
B(Mov), R(3), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4),
B(Star), R(4),
B(LdaImmutableCurrentContextSlot), U8(4),
/* 75 E> */ B(ToName), R(7),
/* 75 E> */ B(ToName), R(6),
B(CreateClosure), U8(3), U8(4), U8(2),
B(Star), R(8),
B(Star), R(7),
B(LdaSmi), I8(2),
B(Star), R(9),
B(Ldar), R(8),
B(StaDataPropertyInLiteral), R(5), R(7), U8(3), U8(6),
B(Star), R(8),
B(Ldar), R(7),
B(StaDataPropertyInLiteral), R(4), R(6), U8(3), U8(6),
B(LdaImmutableCurrentContextSlot), U8(5),
/* 106 E> */ B(ToName), R(7),
/* 106 E> */ B(ToName), R(6),
B(LdaConstant), U8(4),
B(TestEqualStrictNoFeedback), R(7),
B(Mov), R(4), R(6),
B(TestEqualStrictNoFeedback), R(6),
B(Mov), R(3), R(5),
B(JumpIfFalse), U8(7),
B(CallRuntime), U16(Runtime::kThrowStaticPrototypeError), R(0), U8(0),
B(CreateClosure), U8(5), U8(5), U8(2),
B(StaDataPropertyInLiteral), R(6), R(7), U8(3), U8(8),
B(CallRuntime), U16(Runtime::kInstallClassNameAccessorWithCheck), R(4), U8(1),
B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1),
B(StaDataPropertyInLiteral), R(5), R(6), U8(3), U8(8),
B(CallRuntime), U16(Runtime::kInstallClassNameAccessorWithCheck), R(3), U8(1),
B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1),
B(Star), R(0),
B(Star), R(1),
B(Star), R(2),
B(LdaUndefined),
/* 129 S> */ B(Return),
]
@ -184,37 +181,36 @@ snippet: "
class C { constructor() { count++; }}
return new C();
"
frame size: 9
frame size: 8
parameter count: 1
bytecode array length: 64
bytecode array length: 62
bytecodes: [
B(CreateFunctionContext), U8(1),
B(PushContext), R(3),
B(PushContext), R(2),
B(LdaTheHole),
B(Star), R(2),
B(Star), R(1),
/* 30 E> */ B(StackCheck),
/* 46 S> */ B(LdaZero),
/* 46 E> */ B(StaCurrentContextSlot), U8(4),
B(LdaTheHole),
B(Star), R(0),
/* 49 S> */ B(CreateClosure), U8(0), U8(3), U8(2),
B(Star), R(4),
B(CreateClosure), U8(0), U8(3), U8(2),
B(Star), R(3),
B(LdaTheHole),
B(Star), R(5),
B(Star), R(4),
B(LdaSmi), I8(49),
B(Star), R(7),
B(Star), R(6),
B(LdaSmi), I8(86),
B(Star), R(8),
B(Mov), R(4), R(6),
B(CallRuntime), U16(Runtime::kDefineClass), R(5), U8(4),
B(Star), R(5),
B(CallRuntime), U16(Runtime::kInstallClassNameAccessor), R(4), U8(1),
B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1),
B(Star), R(7),
B(Mov), R(3), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4),
B(Star), R(4),
B(CallRuntime), U16(Runtime::kInstallClassNameAccessor), R(3), U8(1),
B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1),
B(Star), R(0),
B(Star), R(1),
B(Star), R(2),
/* 87 S> */ B(Nop),
/* 94 E> */ B(Construct), R(2), R(0), U8(0), U8(4),
/* 94 E> */ B(Construct), R(1), R(0), U8(0), U8(4),
/* 103 S> */ B(Return),
]
constant pool: [
@ -228,51 +224,49 @@ snippet: "
(class {})
class E { static name () {}}
"
frame size: 10
frame size: 8
parameter count: 1
bytecode array length: 102
bytecode array length: 98
bytecodes: [
B(LdaTheHole),
B(Star), R(3),
/* 30 E> */ B(StackCheck),
/* 35 S> */ B(CreateClosure), U8(0), U8(3), U8(2),
B(Star), R(4),
B(LdaTheHole),
B(Star), R(5),
B(LdaSmi), I8(35),
B(Star), R(7),
B(LdaSmi), I8(43),
B(Star), R(8),
B(Mov), R(4), R(6),
B(CallRuntime), U16(Runtime::kDefineClass), R(5), U8(4),
B(Star), R(5),
B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1),
B(Star), R(1),
B(LdaTheHole),
B(Star), R(0),
/* 45 S> */ B(CreateClosure), U8(1), U8(4), U8(2),
B(Star), R(4),
B(LdaTheHole),
B(Star), R(5),
B(LdaSmi), I8(45),
B(Star), R(7),
B(LdaSmi), I8(73),
B(Star), R(8),
B(Mov), R(4), R(6),
B(CallRuntime), U16(Runtime::kDefineClass), R(5), U8(4),
B(Star), R(5),
B(LdaConstant), U8(2),
B(Star), R(7),
B(CreateClosure), U8(3), U8(5), U8(2),
B(Star), R(8),
B(LdaSmi), I8(2),
B(Star), R(9),
B(Ldar), R(8),
B(StaDataPropertyInLiteral), R(6), R(7), U8(1), U8(6),
B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1),
B(Star), R(0),
/* 30 E> */ B(StackCheck),
/* 34 S> */ B(CreateClosure), U8(0), U8(3), U8(2),
B(Star), R(2),
B(LdaTheHole),
B(Star), R(3),
B(LdaSmi), I8(35),
B(Star), R(5),
B(LdaSmi), I8(43),
B(Star), R(6),
B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
B(Star), R(3),
B(CallRuntime), U16(Runtime::kToFastProperties), R(2), U8(1),
B(LdaTheHole),
B(Star), R(0),
B(CreateClosure), U8(1), U8(4), U8(2),
B(Star), R(2),
B(LdaTheHole),
B(Star), R(3),
B(LdaSmi), I8(45),
B(Star), R(5),
B(LdaSmi), I8(73),
B(Star), R(6),
B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
B(Star), R(3),
B(LdaConstant), U8(2),
B(Star), R(5),
B(CreateClosure), U8(3), U8(5), U8(2),
B(Star), R(6),
B(LdaSmi), I8(2),
B(Star), R(7),
B(Ldar), R(6),
B(StaDataPropertyInLiteral), R(4), R(5), U8(1), U8(6),
B(CallRuntime), U16(Runtime::kToFastProperties), R(2), U8(1),
B(Star), R(0),
B(Star), R(1),
B(LdaUndefined),
/* 74 S> */ B(Return),
]

View File

@ -660,7 +660,7 @@ snippet: "
"
frame size: 9
parameter count: 2
bytecode array length: 191
bytecode array length: 187
bytecodes: [
B(Ldar), R(new_target),
B(JumpIfUndefined), U8(27),
@ -720,8 +720,8 @@ bytecodes: [
B(Ldar), R(5),
/* 0 E> */ B(Throw),
B(Ldar), R(5),
B(StaCurrentContextSlot), U8(7),
/* 16 S> */ B(CreateClosure), U8(1), U8(3), U8(0),
B(StaCurrentContextSlot), U8(6),
B(CreateClosure), U8(1), U8(3), U8(0),
B(Star), R(3),
B(LdaTheHole),
B(Star), R(4),
@ -734,10 +734,8 @@ bytecodes: [
B(Star), R(4),
B(CallRuntime), U16(Runtime::kInstallClassNameAccessor), R(3), U8(1),
B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1),
B(StaCurrentContextSlot), U8(6),
B(StaModuleVariable), I8(1), U8(0),
B(LdaCurrentContextSlot), U8(6),
/* 16 E> */ B(StaModuleVariable), I8(1), U8(0),
B(LdaCurrentContextSlot), U8(7),
B(Star), R(3),
B(LdaTrue),
B(Star), R(4),

View File

@ -10,35 +10,34 @@ snippet: "
class A { constructor(...args) { this.args = args; } }
new A(...[1, 2, 3]);
"
frame size: 8
frame size: 7
parameter count: 1
bytecode array length: 64
bytecode array length: 62
bytecodes: [
B(LdaTheHole),
B(Star), R(2),
B(Star), R(1),
/* 30 E> */ B(StackCheck),
B(LdaTheHole),
B(Star), R(0),
/* 34 S> */ B(CreateClosure), U8(0), U8(3), U8(2),
B(Star), R(3),
B(CreateClosure), U8(0), U8(3), U8(2),
B(Star), R(2),
B(LdaTheHole),
B(Star), R(4),
B(Star), R(3),
B(LdaSmi), I8(34),
B(Star), R(6),
B(Star), R(5),
B(LdaSmi), I8(88),
B(Star), R(7),
B(Mov), R(3), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4),
B(Star), R(4),
B(CallRuntime), U16(Runtime::kInstallClassNameAccessor), R(3), U8(1),
B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1),
B(Star), R(6),
B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
B(Star), R(3),
B(CallRuntime), U16(Runtime::kInstallClassNameAccessor), R(2), U8(1),
B(CallRuntime), U16(Runtime::kToFastProperties), R(2), U8(1),
B(Star), R(0),
B(Star), R(1),
B(Star), R(2),
/* 89 S> */ B(CreateArrayLiteral), U8(1), U8(6), U8(17),
B(Star), R(4),
B(Ldar), R(2),
/* 89 E> */ B(ConstructWithSpread), R(2), R(4), U8(1),
B(Star), R(3),
B(Ldar), R(1),
/* 89 E> */ B(ConstructWithSpread), R(1), R(3), U8(1),
B(LdaUndefined),
/* 110 S> */ B(Return),
]
@ -54,37 +53,36 @@ snippet: "
class A { constructor(...args) { this.args = args; } }
new A(0, ...[1, 2, 3]);
"
frame size: 8
frame size: 7
parameter count: 1
bytecode array length: 67
bytecode array length: 65
bytecodes: [
B(LdaTheHole),
B(Star), R(2),
B(Star), R(1),
/* 30 E> */ B(StackCheck),
B(LdaTheHole),
B(Star), R(0),
/* 34 S> */ B(CreateClosure), U8(0), U8(3), U8(2),
B(Star), R(3),
B(CreateClosure), U8(0), U8(3), U8(2),
B(Star), R(2),
B(LdaTheHole),
B(Star), R(4),
B(Star), R(3),
B(LdaSmi), I8(34),
B(Star), R(6),
B(Star), R(5),
B(LdaSmi), I8(88),
B(Star), R(7),
B(Mov), R(3), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4),
B(Star), R(4),
B(CallRuntime), U16(Runtime::kInstallClassNameAccessor), R(3), U8(1),
B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1),
B(Star), R(6),
B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
B(Star), R(3),
B(CallRuntime), U16(Runtime::kInstallClassNameAccessor), R(2), U8(1),
B(CallRuntime), U16(Runtime::kToFastProperties), R(2), U8(1),
B(Star), R(0),
B(Star), R(1),
B(Star), R(2),
/* 89 S> */ B(LdaZero),
B(Star), R(4),
B(Star), R(3),
B(CreateArrayLiteral), U8(1), U8(6), U8(17),
B(Star), R(5),
B(Ldar), R(2),
/* 89 E> */ B(ConstructWithSpread), R(2), R(4), U8(2),
B(Star), R(4),
B(Ldar), R(1),
/* 89 E> */ B(ConstructWithSpread), R(1), R(3), U8(2),
B(LdaUndefined),
/* 113 S> */ B(Return),
]
@ -100,49 +98,48 @@ snippet: "
class A { constructor(...args) { this.args = args; } }
new A(0, ...[1, 2, 3], 4);
"
frame size: 9
frame size: 8
parameter count: 1
bytecode array length: 98
bytecode array length: 96
bytecodes: [
B(LdaTheHole),
B(Star), R(2),
B(Star), R(1),
/* 30 E> */ B(StackCheck),
B(LdaTheHole),
B(Star), R(0),
/* 34 S> */ B(CreateClosure), U8(0), U8(3), U8(2),
B(Star), R(3),
B(CreateClosure), U8(0), U8(3), U8(2),
B(Star), R(2),
B(LdaTheHole),
B(Star), R(4),
B(Star), R(3),
B(LdaSmi), I8(34),
B(Star), R(6),
B(Star), R(5),
B(LdaSmi), I8(88),
B(Star), R(7),
B(Mov), R(3), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4),
B(Star), R(4),
B(CallRuntime), U16(Runtime::kInstallClassNameAccessor), R(3), U8(1),
B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1),
B(Star), R(6),
B(Mov), R(2), R(4),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
B(Star), R(3),
B(CallRuntime), U16(Runtime::kInstallClassNameAccessor), R(2), U8(1),
B(CallRuntime), U16(Runtime::kToFastProperties), R(2), U8(1),
B(Star), R(0),
B(Star), R(1),
B(Star), R(2),
/* 89 S> */ B(LdaUndefined),
B(Star), R(3),
B(Star), R(2),
B(LdaUndefined),
B(Star), R(5),
B(Star), R(4),
/* 93 E> */ B(CreateArrayLiteral), U8(1), U8(4), U8(17),
B(Star), R(6),
B(LdaUndefined),
B(Star), R(7),
B(CreateArrayLiteral), U8(2), U8(5), U8(17),
B(Star), R(8),
B(CallJSRuntime), U8(%spread_iterable), R(7), U8(2),
B(Star), R(7),
B(CreateArrayLiteral), U8(3), U8(6), U8(17),
B(Star), R(8),
B(CallJSRuntime), U8(%spread_arguments), R(5), U8(4),
B(Star), R(5),
B(Mov), R(1), R(4),
B(CallJSRuntime), U8(%reflect_construct), R(3), U8(3),
B(LdaUndefined),
B(Star), R(6),
B(CreateArrayLiteral), U8(2), U8(5), U8(17),
B(Star), R(7),
B(CallJSRuntime), U8(%spread_iterable), R(6), U8(2),
B(Star), R(6),
B(CreateArrayLiteral), U8(3), U8(6), U8(17),
B(Star), R(7),
B(CallJSRuntime), U8(%spread_arguments), R(4), U8(4),
B(Star), R(4),
B(Mov), R(0), R(3),
B(CallJSRuntime), U8(%reflect_construct), R(2), U8(3),
B(LdaUndefined),
/* 116 S> */ B(Return),
]

View File

@ -183,7 +183,7 @@ function testCaughtException() {
|R|}
function testClasses() {
|_|class Cat {
class Cat {
constructor(name) {
|_|this.name = name;
|R|}
@ -191,7 +191,7 @@ function testClasses() {
speak() {
|R|}
}
|_|class Lion extends Cat {
class Lion extends Cat {
constructor(name) {
|C|super(name);
|R|}

View File

@ -746,16 +746,6 @@ break at:
Running test: testClasses
break at:
function testClasses() {
#class Cat {
constructor(name) {
break at:
}
#class Lion extends Cat {
constructor(name) {
break at:
}
#new Lion().speak();

View File

@ -0,0 +1,6 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Crash with --verify-heap
(function*() { for (let { a = class b { } } of [{}]) { } })().next();