From c1970988c0554ebcd14926ef19652d1340f84c1e Mon Sep 17 00:00:00 2001 From: conradw Date: Thu, 30 Jul 2015 03:38:07 -0700 Subject: [PATCH] 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} --- src/compiler/ast-graph-builder.cc | 27 ++++++----------- src/compiler/linkage.cc | 2 ++ src/full-codegen/arm/full-codegen-arm.cc | 24 ++++----------- src/full-codegen/arm64/full-codegen-arm64.cc | 24 ++++----------- src/full-codegen/ia32/full-codegen-ia32.cc | 24 ++++----------- src/full-codegen/mips/full-codegen-mips.cc | 23 ++++---------- .../mips64/full-codegen-mips64.cc | 23 ++++---------- src/full-codegen/ppc/full-codegen-ppc.cc | 23 ++++---------- src/full-codegen/x64/full-codegen-x64.cc | 24 ++++----------- src/full-codegen/x87/full-codegen-x87.cc | 24 ++++----------- src/runtime/runtime-classes.cc | 30 +++++++++++++++++++ src/runtime/runtime.h | 2 ++ 12 files changed, 91 insertions(+), 159 deletions(-) diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc index db61cd1eb8..fa56f8ce07 100644 --- a/src/compiler/ast-graph-builder.cc +++ b/src/compiler/ast-graph-builder.cc @@ -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) { diff --git a/src/compiler/linkage.cc b/src/compiler/linkage.cc index a460f4a980..e71f8233e2 100644 --- a/src/compiler/linkage.cc +++ b/src/compiler/linkage.cc @@ -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? diff --git a/src/full-codegen/arm/full-codegen-arm.cc b/src/full-codegen/arm/full-codegen-arm.cc index e7742b0203..ab74ff02a7 100644 --- a/src/full-codegen/arm/full-codegen-arm.cc +++ b/src/full-codegen/arm/full-codegen-arm.cc @@ -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); } diff --git a/src/full-codegen/arm64/full-codegen-arm64.cc b/src/full-codegen/arm64/full-codegen-arm64.cc index 6cd49002b9..01a6e7e2a1 100644 --- a/src/full-codegen/arm64/full-codegen-arm64.cc +++ b/src/full-codegen/arm64/full-codegen-arm64.cc @@ -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); } diff --git a/src/full-codegen/ia32/full-codegen-ia32.cc b/src/full-codegen/ia32/full-codegen-ia32.cc index d14939b337..53b693378e 100644 --- a/src/full-codegen/ia32/full-codegen-ia32.cc +++ b/src/full-codegen/ia32/full-codegen-ia32.cc @@ -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); } diff --git a/src/full-codegen/mips/full-codegen-mips.cc b/src/full-codegen/mips/full-codegen-mips.cc index f28ba8b9e5..db8828bd13 100644 --- a/src/full-codegen/mips/full-codegen-mips.cc +++ b/src/full-codegen/mips/full-codegen-mips.cc @@ -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); } diff --git a/src/full-codegen/mips64/full-codegen-mips64.cc b/src/full-codegen/mips64/full-codegen-mips64.cc index 50b597652a..c92e5d7f69 100644 --- a/src/full-codegen/mips64/full-codegen-mips64.cc +++ b/src/full-codegen/mips64/full-codegen-mips64.cc @@ -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); } diff --git a/src/full-codegen/ppc/full-codegen-ppc.cc b/src/full-codegen/ppc/full-codegen-ppc.cc index d92048d9db..c86b39dad7 100644 --- a/src/full-codegen/ppc/full-codegen-ppc.cc +++ b/src/full-codegen/ppc/full-codegen-ppc.cc @@ -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); } diff --git a/src/full-codegen/x64/full-codegen-x64.cc b/src/full-codegen/x64/full-codegen-x64.cc index 5256b1a7a1..da8a9d56db 100644 --- a/src/full-codegen/x64/full-codegen-x64.cc +++ b/src/full-codegen/x64/full-codegen-x64.cc @@ -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); } diff --git a/src/full-codegen/x87/full-codegen-x87.cc b/src/full-codegen/x87/full-codegen-x87.cc index dbe8a66934..1945af785d 100644 --- a/src/full-codegen/x87/full-codegen-x87.cc +++ b/src/full-codegen/x87/full-codegen-x87.cc @@ -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); } diff --git a/src/runtime/runtime-classes.cc b/src/runtime/runtime-classes.cc index 92df7fe064..317d34b8f5 100644 --- a/src/runtime/runtime-classes.cc +++ b/src/runtime/runtime-classes.cc @@ -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 result; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, + JSObject::Freeze(constructor)); + return *result; +} + + RUNTIME_FUNCTION(Runtime_ClassGetSourceCode) { HandleScope shs(isolate); DCHECK(args.length() == 1); diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 034fa4e2b8..6d7c8ccbce 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -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) \