From 2077b314d5d5632da29262f610cd70c3c9536515 Mon Sep 17 00:00:00 2001 From: gsathya Date: Fri, 30 Dec 2016 02:29:39 -0800 Subject: [PATCH] [builtins] Add EmitFastNewObject This refactors the logic from within the FastNewObject TF_BUILTIN to a helper method which can be reused in other assemblers. This saves the overhead of setting up the stub and calling into it. A wrapper method is created for functions that don't need to tail call into the runtime. PromiseBuiltinsAssembler and RegexpBuiltinsAssembler are refactored to use EmitFastNewObject. Review-Url: https://codereview.chromium.org/2607233002 Cr-Commit-Position: refs/heads/master@{#42000} --- src/builtins/builtins-constructor.cc | 52 ++++++++++++++++++++++------ src/builtins/builtins-constructor.h | 5 +++ src/builtins/builtins-promise.cc | 7 ++-- src/builtins/builtins-regexp.cc | 7 ++-- 4 files changed, 54 insertions(+), 17 deletions(-) diff --git a/src/builtins/builtins-constructor.cc b/src/builtins/builtins-constructor.cc index 241c6d6458..58a6860b0c 100644 --- a/src/builtins/builtins-constructor.cc +++ b/src/builtins/builtins-constructor.cc @@ -161,30 +161,57 @@ TF_BUILTIN(FastNewObject, ConstructorBuiltinsAssembler) { Node* target = Parameter(Descriptor::kTarget); Node* new_target = Parameter(Descriptor::kNewTarget); + Label call_runtime(this); + + Node* result = EmitFastNewObject(context, target, new_target, &call_runtime); + Return(result); + + Bind(&call_runtime); + TailCallRuntime(Runtime::kNewObject, context, target, new_target); +} + +Node* ConstructorBuiltinsAssembler::EmitFastNewObject(Node* context, + Node* target, + Node* new_target) { + Variable var_obj(this, MachineRepresentation::kTagged); + Label call_runtime(this), end(this); + + Node* result = EmitFastNewObject(context, target, new_target, &call_runtime); + var_obj.Bind(result); + Goto(&end); + + Bind(&call_runtime); + var_obj.Bind(CallRuntime(Runtime::kNewObject, context, target, new_target)); + Goto(&end); + + Bind(&end); + return var_obj.value(); +} + +Node* ConstructorBuiltinsAssembler::EmitFastNewObject( + Node* context, Node* target, Node* new_target, + CodeAssemblerLabel* call_runtime) { CSA_ASSERT(this, HasInstanceType(target, JS_FUNCTION_TYPE)); CSA_ASSERT(this, IsJSReceiver(new_target)); // Verify that the new target is a JSFunction. - Label runtime(this), fast(this); + Label fast(this), end(this); GotoIf(HasInstanceType(new_target, JS_FUNCTION_TYPE), &fast); - Goto(&runtime); - - Bind(&runtime); - TailCallRuntime(Runtime::kNewObject, context, target, new_target); + Goto(call_runtime); Bind(&fast); // Load the initial map and verify that it's in fact a map. Node* initial_map = LoadObjectField(new_target, JSFunction::kPrototypeOrInitialMapOffset); - GotoIf(TaggedIsSmi(initial_map), &runtime); - GotoIf(DoesntHaveInstanceType(initial_map, MAP_TYPE), &runtime); + GotoIf(TaggedIsSmi(initial_map), call_runtime); + GotoIf(DoesntHaveInstanceType(initial_map, MAP_TYPE), call_runtime); // Fall back to runtime if the target differs from the new target's // initial map constructor. Node* new_target_constructor = LoadObjectField(initial_map, Map::kConstructorOrBackPointerOffset); - GotoIf(WordNotEqual(target, new_target_constructor), &runtime); + GotoIf(WordNotEqual(target, new_target_constructor), call_runtime); Node* instance_size_words = ChangeUint32ToWord(LoadObjectField( initial_map, Map::kInstanceSizeOffset, MachineType::Uint8())); @@ -214,7 +241,7 @@ TF_BUILTIN(FastNewObject, ConstructorBuiltinsAssembler) { Comment("no slack tracking"); InitializeFieldsWithRoot(object, IntPtrConstant(JSObject::kHeaderSize), instance_size, Heap::kUndefinedValueRootIndex); - Return(object); + Goto(&end); } { @@ -243,7 +270,7 @@ TF_BUILTIN(FastNewObject, ConstructorBuiltinsAssembler) { Comment("initialize undefined fields (no finalize)"); InitializeFieldsWithRoot(object, IntPtrConstant(JSObject::kHeaderSize), used_size, Heap::kUndefinedValueRootIndex); - Return(object); + Goto(&end); } { @@ -265,8 +292,11 @@ TF_BUILTIN(FastNewObject, ConstructorBuiltinsAssembler) { used_size, Heap::kUndefinedValueRootIndex); CallRuntime(Runtime::kFinalizeInstanceSize, context, initial_map); - Return(object); + Goto(&end); } + + Bind(&end); + return object; } Node* ConstructorBuiltinsAssembler::EmitFastNewFunctionContext( diff --git a/src/builtins/builtins-constructor.h b/src/builtins/builtins-constructor.h index 86c412b91f..98df636261 100644 --- a/src/builtins/builtins-constructor.h +++ b/src/builtins/builtins-constructor.h @@ -44,6 +44,11 @@ class ConstructorBuiltinsAssembler : public CodeStubAssembler { Node* properties_count); void CreateFastCloneShallowObjectBuiltin(int properties_count); + Node* EmitFastNewObject(Node* context, Node* target, Node* new_target); + + Node* EmitFastNewObject(Node* context, Node* target, Node* new_target, + CodeAssemblerLabel* call_runtime); + private: static const int kMaximumSlots = 0x8000; static const int kSmallMaximumSlots = 10; diff --git a/src/builtins/builtins-promise.cc b/src/builtins/builtins-promise.cc index 88730bf436..9a6a8fe275 100644 --- a/src/builtins/builtins-promise.cc +++ b/src/builtins/builtins-promise.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "src/builtins/builtins-promise.h" +#include "src/builtins/builtins-constructor.h" #include "src/builtins/builtins-utils.h" #include "src/builtins/builtins.h" #include "src/code-factory.h" @@ -742,9 +743,9 @@ TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) { Bind(&if_targetismodified); { - Callable fast_new_object_stub = CodeFactory::FastNewObject(isolate); - Node* const instance = - CallStub(fast_new_object_stub, context, promise_fun, new_target); + ConstructorBuiltinsAssembler constructor_assembler(this->state()); + Node* const instance = constructor_assembler.EmitFastNewObject( + context, promise_fun, new_target); var_result.Bind(instance); Goto(&init); diff --git a/src/builtins/builtins-regexp.cc b/src/builtins/builtins-regexp.cc index bcab141cc7..2191268441 100644 --- a/src/builtins/builtins-regexp.cc +++ b/src/builtins/builtins-regexp.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "src/builtins/builtins-constructor.h" #include "src/builtins/builtins-utils.h" #include "src/builtins/builtins.h" #include "src/code-factory.h" @@ -786,9 +787,9 @@ TF_BUILTIN(RegExpConstructor, RegExpBuiltinsAssembler) { Bind(&allocate_generic); { - Callable fastnewobject_callable = CodeFactory::FastNewObject(isolate); - Node* const regexp = CallStub(fastnewobject_callable, context, - regexp_function, var_new_target.value()); + ConstructorBuiltinsAssembler constructor_assembler(this->state()); + Node* const regexp = constructor_assembler.EmitFastNewObject( + context, regexp_function, var_new_target.value()); var_regexp.Bind(regexp); Goto(&next); }