Commit 3e20d381 authored by adamk's avatar adamk Committed by Commit bot

[ignition] Only initialize [[HomeObject]] for class constructors if needed

This moves the initialization of [[HomeObject]] for constructors from
the %DefineClass runtime function into the bytecode generator, and
makes it conditional (resolving an old TODO). As part of this refactor,
avoid a load of "prototype" by returning the class prototype from
%DefineClass.

This is one of many steps in moving more of class definition into
bytecode.

R=rmcilroy@chromium.org

Review-Url: https://codereview.chromium.org/2610683003
Cr-Commit-Position: refs/heads/master@{#42072}
parent f81590a1
......@@ -367,8 +367,11 @@ void ClassLiteral::AssignFeedbackVectorSlots(Isolate* isolate,
FeedbackVectorSpec* spec,
FeedbackVectorSlotCache* cache) {
// This logic that computes the number of slots needed for vector store
// ICs must mirror FullCodeGenerator::VisitClassLiteral.
prototype_slot_ = spec->AddLoadICSlot();
// ICs must mirror BytecodeGenerator::VisitClassLiteral.
if (FunctionLiteral::NeedsHomeObject(constructor())) {
home_object_slot_ = spec->AddStoreICSlot();
}
if (NeedsProxySlot()) {
proxy_slot_ = spec->AddStoreICSlot();
}
......
......@@ -2795,7 +2795,7 @@ class ClassLiteral final : public Expression {
class_variable_proxy()->var()->IsUnallocated();
}
FeedbackVectorSlot PrototypeSlot() const { return prototype_slot_; }
FeedbackVectorSlot HomeObjectSlot() const { return home_object_slot_; }
FeedbackVectorSlot ProxySlot() const { return proxy_slot_; }
private:
......@@ -2816,7 +2816,7 @@ class ClassLiteral final : public Expression {
}
int end_position_;
FeedbackVectorSlot prototype_slot_;
FeedbackVectorSlot home_object_slot_;
FeedbackVectorSlot proxy_slot_;
VariableProxy* class_variable_proxy_;
Expression* extends_;
......
......@@ -1411,20 +1411,33 @@ void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
}
void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
VisitClassLiteralForRuntimeDefinition(expr);
// Load the "prototype" from the constructor.
Register literal = register_allocator()->NewRegister();
Register constructor = VisitForRegisterValue(expr->constructor());
{
RegisterAllocationScope register_scope(this);
RegisterList args = register_allocator()->NewRegisterList(4);
VisitForAccumulatorValueOrTheHole(expr->extends());
builder()
->StoreAccumulatorInRegister(args[0])
.MoveRegister(constructor, args[1])
.LoadLiteral(Smi::FromInt(expr->start_position()))
.StoreAccumulatorInRegister(args[2])
.LoadLiteral(Smi::FromInt(expr->end_position()))
.StoreAccumulatorInRegister(args[3])
.CallRuntime(Runtime::kDefineClass, args);
}
Register prototype = register_allocator()->NewRegister();
FeedbackVectorSlot slot = expr->PrototypeSlot();
builder()
->StoreAccumulatorInRegister(literal)
.LoadNamedProperty(literal, prototype_string(), feedback_index(slot))
.StoreAccumulatorInRegister(prototype);
builder()->StoreAccumulatorInRegister(prototype);
VisitClassLiteralProperties(expr, literal, prototype);
BuildClassLiteralNameProperty(expr, literal);
builder()->CallRuntime(Runtime::kToFastProperties, literal);
if (FunctionLiteral::NeedsHomeObject(expr->constructor())) {
// Prototype is already in the accumulator.
builder()->StoreNamedProperty(constructor, home_object_symbol(),
feedback_index(expr->HomeObjectSlot()),
language_mode());
}
VisitClassLiteralProperties(expr, constructor, prototype);
BuildClassLiteralNameProperty(expr, constructor);
builder()->CallRuntime(Runtime::kToFastProperties, constructor);
// Assign to class variable.
if (expr->class_variable_proxy() != nullptr) {
VariableProxy* proxy = expr->class_variable_proxy();
......@@ -1436,23 +1449,8 @@ void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
}
}
void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition(
ClassLiteral* expr) {
RegisterAllocationScope register_scope(this);
RegisterList args = register_allocator()->NewRegisterList(4);
VisitForAccumulatorValueOrTheHole(expr->extends());
builder()->StoreAccumulatorInRegister(args[0]);
VisitForRegisterValue(expr->constructor(), args[1]);
builder()
->LoadLiteral(Smi::FromInt(expr->start_position()))
.StoreAccumulatorInRegister(args[2])
.LoadLiteral(Smi::FromInt(expr->end_position()))
.StoreAccumulatorInRegister(args[3])
.CallRuntime(Runtime::kDefineClass, args);
}
void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr,
Register literal,
Register constructor,
Register prototype) {
RegisterAllocationScope register_scope(this);
RegisterList args = register_allocator()->NewRegisterList(4);
......@@ -1466,7 +1464,7 @@ void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr,
ClassLiteral::Property* property = expr->properties()->at(i);
// Set-up receiver.
Register new_receiver = property->is_static() ? literal : prototype;
Register new_receiver = property->is_static() ? constructor : prototype;
if (new_receiver != old_receiver) {
builder()->MoveRegister(new_receiver, receiver);
old_receiver = new_receiver;
......
......@@ -130,10 +130,9 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
void VisitArgumentsObject(Variable* variable);
void VisitRestArgumentsArray(Variable* rest);
void VisitCallSuper(Call* call);
void VisitClassLiteralForRuntimeDefinition(ClassLiteral* expr);
void VisitClassLiteralProperties(ClassLiteral* expr, Register literal,
void VisitClassLiteralProperties(ClassLiteral* expr, Register constructor,
Register prototype);
void BuildClassLiteralNameProperty(ClassLiteral* expr, Register literal);
void BuildClassLiteralNameProperty(ClassLiteral* expr, Register constructor);
void VisitThisFunctionVariable(Variable* variable);
void VisitNewTargetVariable(Variable* variable);
void VisitBlockDeclarationsAndStatements(Block* stmt);
......
......@@ -167,13 +167,6 @@ static MaybeHandle<Object> DefineClass(Isolate* isolate,
prototype, attribs),
Object);
// TODO(arv): Only do this conditionally.
Handle<Symbol> home_object_symbol(isolate->heap()->home_object_symbol());
RETURN_ON_EXCEPTION(
isolate, JSObject::SetOwnPropertyIgnoreAttributes(
constructor, home_object_symbol, prototype, DONT_ENUM),
Object);
if (!constructor_parent.is_null()) {
MAYBE_RETURN_NULL(JSObject::SetPrototype(constructor, constructor_parent,
false, Object::THROW_ON_ERROR));
......@@ -195,7 +188,8 @@ static MaybeHandle<Object> DefineClass(Isolate* isolate,
handle(Smi::FromInt(end_position), isolate), STRICT),
Object);
return constructor;
// Caller already has access to constructor, so return the prototype.
return prototype;
}
......
......@@ -14,28 +14,27 @@ snippet: "
"
frame size: 8
parameter count: 1
bytecode array length: 72
bytecode array length: 69
bytecodes: [
B(LdaTheHole),
B(Star), R(2),
/* 30 E> */ B(StackCheck),
B(LdaTheHole),
B(Star), R(0),
/* 34 S> */ B(LdaTheHole),
/* 34 S> */ B(CreateClosure), U8(0), U8(2),
B(Star), R(3),
B(CreateClosure), U8(0), U8(2),
B(LdaTheHole),
B(Star), R(4),
B(LdaSmi), U8(34),
B(Star), R(5),
B(Wide), B(LdaSmi), U16(148),
B(Star), R(6),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
B(Star), R(3),
B(LdaNamedProperty), R(3), U8(1), U8(2),
B(Wide), B(LdaSmi), U16(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(2),
B(LdaConstant), U8(1),
B(ToName), R(6),
B(CreateClosure), U8(3), U8(2),
B(CreateClosure), U8(2), U8(2),
B(Star), R(7),
B(LdaSmi), U8(2),
B(StaDataPropertyInLiteral), R(4), R(6), R(7), U8(1),
......@@ -49,7 +48,6 @@ bytecodes: [
]
constant pool: [
SHARED_FUNCTION_INFO_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["prototype"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["speak"],
SHARED_FUNCTION_INFO_TYPE,
]
......@@ -65,28 +63,27 @@ snippet: "
"
frame size: 8
parameter count: 1
bytecode array length: 72
bytecode array length: 69
bytecodes: [
B(LdaTheHole),
B(Star), R(2),
/* 30 E> */ B(StackCheck),
B(LdaTheHole),
B(Star), R(0),
/* 34 S> */ B(LdaTheHole),
/* 34 S> */ B(CreateClosure), U8(0), U8(2),
B(Star), R(3),
B(CreateClosure), U8(0), U8(2),
B(LdaTheHole),
B(Star), R(4),
B(LdaSmi), U8(34),
B(Star), R(5),
B(Wide), B(LdaSmi), U16(148),
B(Star), R(6),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
B(Star), R(3),
B(LdaNamedProperty), R(3), U8(1), U8(2),
B(Wide), B(LdaSmi), U16(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(2),
B(LdaConstant), U8(1),
B(ToName), R(6),
B(CreateClosure), U8(3), U8(2),
B(CreateClosure), U8(2), U8(2),
B(Star), R(7),
B(LdaSmi), U8(2),
B(StaDataPropertyInLiteral), R(4), R(6), R(7), U8(1),
......@@ -100,7 +97,6 @@ bytecodes: [
]
constant pool: [
SHARED_FUNCTION_INFO_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["prototype"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["speak"],
SHARED_FUNCTION_INFO_TYPE,
]
......@@ -118,7 +114,7 @@ snippet: "
"
frame size: 10
parameter count: 1
bytecode array length: 115
bytecode array length: 112
bytecodes: [
B(CreateFunctionContext), U8(2),
B(PushContext), R(3),
......@@ -131,28 +127,27 @@ bytecodes: [
/* 57 E> */ B(StaCurrentContextSlot), U8(5),
B(LdaTheHole),
B(Star), R(0),
/* 62 S> */ B(LdaTheHole),
/* 62 S> */ B(CreateClosure), U8(2), U8(2),
B(Star), R(4),
B(CreateClosure), U8(2), U8(2),
B(LdaTheHole),
B(Star), R(5),
B(LdaSmi), U8(62),
B(Star), R(6),
B(Wide), B(LdaSmi), U16(128),
B(Star), R(7),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4),
B(Star), R(4),
B(LdaNamedProperty), R(4), U8(3), U8(2),
B(Wide), B(LdaSmi), U16(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(LdaCurrentContextSlot), U8(4),
/* 75 E> */ B(ToName), R(7),
B(CreateClosure), U8(4), U8(2),
B(CreateClosure), U8(3), U8(2),
B(Star), R(8),
B(LdaSmi), U8(2),
B(StaDataPropertyInLiteral), R(5), R(7), R(8), U8(3),
B(Star), R(9),
B(LdaCurrentContextSlot), U8(5),
/* 106 E> */ B(ToName), R(7),
B(LdaConstant), U8(3),
B(LdaConstant), U8(4),
B(TestEqualStrict), R(7), U8(0),
B(Mov), R(4), R(6),
B(JumpIfToBooleanFalse), U8(7),
......@@ -172,8 +167,8 @@ constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE ["a"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["b"],
SHARED_FUNCTION_INFO_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["prototype"],
SHARED_FUNCTION_INFO_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["prototype"],
SHARED_FUNCTION_INFO_TYPE,
]
handlers: [
......@@ -185,9 +180,9 @@ snippet: "
class C { constructor() { count++; }}
return new C();
"
frame size: 8
frame size: 9
parameter count: 1
bytecode array length: 66
bytecode array length: 63
bytecodes: [
B(CreateFunctionContext), U8(1),
B(PushContext), R(3),
......@@ -198,17 +193,16 @@ bytecodes: [
/* 46 E> */ B(StaCurrentContextSlot), U8(4),
B(LdaTheHole),
B(Star), R(0),
/* 49 S> */ B(LdaTheHole),
/* 49 S> */ B(CreateClosure), U8(0), U8(2),
B(Star), R(4),
B(CreateClosure), U8(0), U8(2),
B(LdaTheHole),
B(Star), R(5),
B(LdaSmi), U8(49),
B(Star), R(6),
B(LdaSmi), U8(86),
B(Star), R(7),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4),
B(Star), R(4),
B(LdaNamedProperty), R(4), U8(1), U8(2),
B(LdaSmi), U8(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),
......@@ -216,12 +210,11 @@ bytecodes: [
B(Star), R(1),
B(Star), R(2),
/* 87 S> */ B(Nop),
/* 94 E> */ B(New), R(2), R(0), U8(0), U8(4),
/* 94 E> */ B(New), R(2), R(0), U8(0), U8(2),
/* 103 S> */ B(Return),
]
constant pool: [
SHARED_FUNCTION_INFO_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["prototype"],
]
handlers: [
]
......@@ -233,45 +226,43 @@ snippet: "
"
frame size: 9
parameter count: 1
bytecode array length: 101
bytecode array length: 95
bytecodes: [
B(LdaTheHole),
B(Star), R(3),
/* 30 E> */ B(StackCheck),
/* 35 S> */ B(LdaTheHole),
/* 35 S> */ B(CreateClosure), U8(0), U8(2),
B(Star), R(4),
B(CreateClosure), U8(0), U8(2),
B(LdaTheHole),
B(Star), R(5),
B(LdaSmi), U8(35),
B(Star), R(6),
B(LdaSmi), U8(43),
B(Star), R(7),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4),
B(Star), R(4),
B(LdaNamedProperty), R(4), U8(1), U8(2),
B(LdaSmi), U8(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(LdaTheHole),
/* 45 S> */ B(CreateClosure), U8(1), U8(2),
B(Star), R(4),
B(CreateClosure), U8(2), U8(2),
B(LdaTheHole),
B(Star), R(5),
B(LdaSmi), U8(45),
B(Star), R(6),
B(LdaSmi), U8(73),
B(Star), R(7),
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4),
B(Star), R(4),
B(LdaNamedProperty), R(4), U8(1), U8(4),
B(LdaSmi), U8(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(3),
B(LdaConstant), U8(2),
B(ToName), R(7),
B(CreateClosure), U8(4), U8(2),
B(CreateClosure), U8(3), U8(2),
B(Star), R(8),
B(LdaSmi), U8(2),
B(StaDataPropertyInLiteral), R(4), R(7), R(8), U8(1),
B(StaDataPropertyInLiteral), R(6), R(7), R(8), U8(1),
B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1),
B(Star), R(0),
B(Star), R(2),
......@@ -281,7 +272,6 @@ bytecodes: [
]
constant pool: [
SHARED_FUNCTION_INFO_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["prototype"],
SHARED_FUNCTION_INFO_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["name"],
SHARED_FUNCTION_INFO_TYPE,
......
......@@ -603,7 +603,7 @@ snippet: "
"
frame size: 8
parameter count: 2
bytecode array length: 175
bytecode array length: 172
bytecodes: [
B(Ldar), R(new_target),
B(JumpIfUndefined), U8(21),
......@@ -660,17 +660,16 @@ bytecodes: [
/* 26 S> */ B(Return),
B(Ldar), R(4),
/* 0 E> */ B(Throw),
/* 16 S> */ B(LdaTheHole),
/* 16 S> */ B(CreateClosure), U8(1), U8(0),
B(Star), R(2),
B(CreateClosure), U8(1), U8(0),
B(LdaTheHole),
B(Star), R(3),
B(LdaSmi), U8(16),
B(Star), R(4),
B(LdaSmi), U8(24),
B(Star), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(2), U8(4),
B(Star), R(2),
B(LdaNamedProperty), R(2), U8(2), U8(2),
B(LdaSmi), U8(24),
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),
......@@ -683,7 +682,6 @@ bytecodes: [
constant pool: [
FIXED_ARRAY_TYPE,
SHARED_FUNCTION_INFO_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["prototype"],
]
handlers: [
]
......
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