Move final parts of class literal setup into a single runtime call

This avoids multiple ToFastProperties runtime calls and additional stack
pushes in strong mode.

BUG=

Review URL: https://codereview.chromium.org/1266573003

Cr-Commit-Position: refs/heads/master@{#29925}
This commit is contained in:
conradw 2015-07-30 03:38:07 -07:00 committed by Commit bot
parent f469b21143
commit c1970988c0
12 changed files with 91 additions and 159 deletions

View File

@ -1639,24 +1639,15 @@ void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
}
}
// Transform both the class literal and the prototype to fast properties.
const Operator* op = javascript()->CallRuntime(Runtime::kToFastProperties, 1);
NewNode(op, environment()->Pop()); // prototype
NewNode(op, environment()->Pop()); // literal
if (is_strong(language_mode())) {
// TODO(conradw): It would be more efficient to define the properties with
// the right attributes the first time round.
// Freeze the prototype.
proto =
NewNode(javascript()->CallRuntime(Runtime::kObjectFreeze, 1), proto);
// Freezing the prototype should never deopt.
PrepareFrameState(proto, BailoutId::None());
// Freeze the constructor.
literal =
NewNode(javascript()->CallRuntime(Runtime::kObjectFreeze, 1), literal);
// Freezing the constructor should never deopt.
PrepareFrameState(literal, BailoutId::None());
}
// Set both the prototype and constructor to have fast properties, and also
// freeze them in strong mode.
environment()->Pop(); // proto
environment()->Pop(); // literal
const Operator* op = javascript()->CallRuntime(
is_strong(language_mode()) ? Runtime::kFinalizeClassDefinitionStrong
: Runtime::kFinalizeClassDefinition,
2);
literal = NewNode(op, literal, proto);
// Assign to class variable.
if (expr->scope() != NULL) {

View File

@ -192,6 +192,8 @@ int Linkage::FrameStateInputCount(Runtime::FunctionId function) {
switch (function) {
case Runtime::kAllocateInTargetSpace:
case Runtime::kDateField:
case Runtime::kFinalizeClassDefinition: // TODO(conradw): Is it safe?
case Runtime::kFinalizeClassDefinitionStrong: // TODO(conradw): Is it safe?
case Runtime::kDefineClassMethod: // TODO(jarin): Is it safe?
case Runtime::kDefineGetterPropertyUnchecked: // TODO(jarin): Is it safe?
case Runtime::kDefineSetterPropertyUnchecked: // TODO(jarin): Is it safe?

View File

@ -2567,24 +2567,12 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
}
}
// prototype
__ CallRuntime(Runtime::kToFastProperties, 1);
// constructor
__ CallRuntime(Runtime::kToFastProperties, 1);
if (is_strong(language_mode())) {
__ ldr(scratch,
FieldMemOperand(r0, JSFunction::kPrototypeOrInitialMapOffset));
__ push(r0);
__ push(scratch);
// TODO(conradw): It would be more efficient to define the properties with
// the right attributes the first time round.
// Freeze the prototype.
__ CallRuntime(Runtime::kObjectFreeze, 1);
// Freeze the constructor.
__ CallRuntime(Runtime::kObjectFreeze, 1);
}
// Set both the prototype and constructor to have fast properties, and also
// freeze them in strong mode.
__ CallRuntime(is_strong(language_mode())
? Runtime::kFinalizeClassDefinitionStrong
: Runtime::kFinalizeClassDefinition,
2);
}

View File

@ -2263,24 +2263,12 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
}
}
// prototype
__ CallRuntime(Runtime::kToFastProperties, 1);
// constructor
__ CallRuntime(Runtime::kToFastProperties, 1);
if (is_strong(language_mode())) {
__ Ldr(scratch,
FieldMemOperand(x0, JSFunction::kPrototypeOrInitialMapOffset));
__ push(x0);
__ Push(scratch);
// TODO(conradw): It would be more efficient to define the properties with
// the right attributes the first time round.
// Freeze the prototype.
__ CallRuntime(Runtime::kObjectFreeze, 1);
// Freeze the constructor.
__ CallRuntime(Runtime::kObjectFreeze, 1);
}
// Set both the prototype and constructor to have fast properties, and also
// freeze them in strong mode.
__ CallRuntime(is_strong(language_mode())
? Runtime::kFinalizeClassDefinitionStrong
: Runtime::kFinalizeClassDefinition,
2);
}

View File

@ -2479,24 +2479,12 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
}
}
// prototype
__ CallRuntime(Runtime::kToFastProperties, 1);
// constructor
__ CallRuntime(Runtime::kToFastProperties, 1);
if (is_strong(language_mode())) {
__ mov(scratch,
FieldOperand(eax, JSFunction::kPrototypeOrInitialMapOffset));
__ push(eax);
__ Push(scratch);
// TODO(conradw): It would be more efficient to define the properties with
// the right attributes the first time round.
// Freeze the prototype.
__ CallRuntime(Runtime::kObjectFreeze, 1);
// Freeze the constructor.
__ CallRuntime(Runtime::kObjectFreeze, 1);
}
// Set both the prototype and constructor to have fast properties, and also
// freeze them in strong mode.
__ CallRuntime(is_strong(language_mode())
? Runtime::kFinalizeClassDefinitionStrong
: Runtime::kFinalizeClassDefinition,
2);
}

View File

@ -2558,23 +2558,12 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
}
}
// prototype
__ CallRuntime(Runtime::kToFastProperties, 1);
// constructor
__ CallRuntime(Runtime::kToFastProperties, 1);
if (is_strong(language_mode())) {
__ lw(scratch,
FieldMemOperand(v0, JSFunction::kPrototypeOrInitialMapOffset));
__ Push(v0, scratch);
// TODO(conradw): It would be more efficient to define the properties with
// the right attributes the first time round.
// Freeze the prototype.
__ CallRuntime(Runtime::kObjectFreeze, 1);
// Freeze the constructor.
__ CallRuntime(Runtime::kObjectFreeze, 1);
}
// Set both the prototype and constructor to have fast properties, and also
// freeze them in strong mode.
__ CallRuntime(is_strong(language_mode())
? Runtime::kFinalizeClassDefinitionStrong
: Runtime::kFinalizeClassDefinition,
2);
}

View File

@ -2555,23 +2555,12 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
}
}
// prototype
__ CallRuntime(Runtime::kToFastProperties, 1);
// constructor
__ CallRuntime(Runtime::kToFastProperties, 1);
if (is_strong(language_mode())) {
__ ld(scratch,
FieldMemOperand(v0, JSFunction::kPrototypeOrInitialMapOffset));
__ Push(v0, scratch);
// TODO(conradw): It would be more efficient to define the properties with
// the right attributes the first time round.
// Freeze the prototype.
__ CallRuntime(Runtime::kObjectFreeze, 1);
// Freeze the constructor.
__ CallRuntime(Runtime::kObjectFreeze, 1);
}
// Set both the prototype and constructor to have fast properties, and also
// freeze them in strong mode.
__ CallRuntime(is_strong(language_mode())
? Runtime::kFinalizeClassDefinitionStrong
: Runtime::kFinalizeClassDefinition,
2);
}

View File

@ -2572,23 +2572,12 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
}
}
// prototype
__ CallRuntime(Runtime::kToFastProperties, 1);
// constructor
__ CallRuntime(Runtime::kToFastProperties, 1);
if (is_strong(language_mode())) {
__ LoadP(scratch,
FieldMemOperand(r3, JSFunction::kPrototypeOrInitialMapOffset));
__ Push(r3, scratch);
// TODO(conradw): It would be more efficient to define the properties with
// the right attributes the first time round.
// Freeze the prototype.
__ CallRuntime(Runtime::kObjectFreeze, 1);
// Freeze the constructor.
__ CallRuntime(Runtime::kObjectFreeze, 1);
}
// Set both the prototype and constructor to have fast properties, and also
// freeze them in strong mode.
__ CallRuntime(is_strong(language_mode())
? Runtime::kFinalizeClassDefinitionStrong
: Runtime::kFinalizeClassDefinition,
2);
}

View File

@ -2474,24 +2474,12 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
}
}
// prototype
__ CallRuntime(Runtime::kToFastProperties, 1);
// constructor
__ CallRuntime(Runtime::kToFastProperties, 1);
if (is_strong(language_mode())) {
__ movp(scratch,
FieldOperand(rax, JSFunction::kPrototypeOrInitialMapOffset));
__ Push(rax);
__ Push(scratch);
// TODO(conradw): It would be more efficient to define the properties with
// the right attributes the first time round.
// Freeze the prototype.
__ CallRuntime(Runtime::kObjectFreeze, 1);
// Freeze the constructor.
__ CallRuntime(Runtime::kObjectFreeze, 1);
}
// Set both the prototype and constructor to have fast properties, and also
// freeze them in strong mode.
__ CallRuntime(is_strong(language_mode())
? Runtime::kFinalizeClassDefinitionStrong
: Runtime::kFinalizeClassDefinition,
2);
}

View File

@ -2470,24 +2470,12 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
}
}
// prototype
__ CallRuntime(Runtime::kToFastProperties, 1);
// constructor
__ CallRuntime(Runtime::kToFastProperties, 1);
if (is_strong(language_mode())) {
__ mov(scratch,
FieldOperand(eax, JSFunction::kPrototypeOrInitialMapOffset));
__ push(eax);
__ push(scratch);
// TODO(conradw): It would be more efficient to define the properties with
// the right attributes the first time round.
// Freeze the prototype.
__ CallRuntime(Runtime::kObjectFreeze, 1);
// Freeze the constructor.
__ CallRuntime(Runtime::kObjectFreeze, 1);
}
// Set both the prototype and constructor to have fast properties, and also
// freeze them in strong mode.
__ CallRuntime(is_strong(language_mode())
? Runtime::kFinalizeClassDefinitionStrong
: Runtime::kFinalizeClassDefinition,
2);
}

View File

@ -253,6 +253,36 @@ RUNTIME_FUNCTION(Runtime_DefineClassMethod) {
}
RUNTIME_FUNCTION(Runtime_FinalizeClassDefinition) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, constructor, 0);
CONVERT_ARG_HANDLE_CHECKED(JSObject, prototype, 1);
JSObject::MigrateSlowToFast(prototype, 0, "RuntimeToFastProperties");
JSObject::MigrateSlowToFast(constructor, 0, "RuntimeToFastProperties");
return *constructor;
}
RUNTIME_FUNCTION(Runtime_FinalizeClassDefinitionStrong) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, constructor, 0);
CONVERT_ARG_HANDLE_CHECKED(JSObject, prototype, 1);
JSObject::MigrateSlowToFast(prototype, 0, "RuntimeToFastProperties");
JSObject::MigrateSlowToFast(constructor, 0, "RuntimeToFastProperties");
RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::Freeze(prototype));
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
JSObject::Freeze(constructor));
return *result;
}
RUNTIME_FUNCTION(Runtime_ClassGetSourceCode) {
HandleScope shs(isolate);
DCHECK(args.length() == 1);

View File

@ -84,6 +84,8 @@ namespace internal {
F(HomeObjectSymbol, 0, 1) \
F(DefineClass, 6, 1) \
F(DefineClassStrong, 6, 1) \
F(FinalizeClassDefinition, 2, 1) \
F(FinalizeClassDefinitionStrong, 2, 1) \
F(DefineClassMethod, 3, 1) \
F(ClassGetSourceCode, 1, 1) \
F(LoadFromSuper, 4, 1) \