[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}
This commit is contained in:
parent
1542a47f59
commit
2077b314d5
@ -161,30 +161,57 @@ TF_BUILTIN(FastNewObject, ConstructorBuiltinsAssembler) {
|
|||||||
Node* target = Parameter(Descriptor::kTarget);
|
Node* target = Parameter(Descriptor::kTarget);
|
||||||
Node* new_target = Parameter(Descriptor::kNewTarget);
|
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, HasInstanceType(target, JS_FUNCTION_TYPE));
|
||||||
CSA_ASSERT(this, IsJSReceiver(new_target));
|
CSA_ASSERT(this, IsJSReceiver(new_target));
|
||||||
|
|
||||||
// Verify that the new target is a JSFunction.
|
// 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);
|
GotoIf(HasInstanceType(new_target, JS_FUNCTION_TYPE), &fast);
|
||||||
Goto(&runtime);
|
Goto(call_runtime);
|
||||||
|
|
||||||
Bind(&runtime);
|
|
||||||
TailCallRuntime(Runtime::kNewObject, context, target, new_target);
|
|
||||||
|
|
||||||
Bind(&fast);
|
Bind(&fast);
|
||||||
|
|
||||||
// Load the initial map and verify that it's in fact a map.
|
// Load the initial map and verify that it's in fact a map.
|
||||||
Node* initial_map =
|
Node* initial_map =
|
||||||
LoadObjectField(new_target, JSFunction::kPrototypeOrInitialMapOffset);
|
LoadObjectField(new_target, JSFunction::kPrototypeOrInitialMapOffset);
|
||||||
GotoIf(TaggedIsSmi(initial_map), &runtime);
|
GotoIf(TaggedIsSmi(initial_map), call_runtime);
|
||||||
GotoIf(DoesntHaveInstanceType(initial_map, MAP_TYPE), &runtime);
|
GotoIf(DoesntHaveInstanceType(initial_map, MAP_TYPE), call_runtime);
|
||||||
|
|
||||||
// Fall back to runtime if the target differs from the new target's
|
// Fall back to runtime if the target differs from the new target's
|
||||||
// initial map constructor.
|
// initial map constructor.
|
||||||
Node* new_target_constructor =
|
Node* new_target_constructor =
|
||||||
LoadObjectField(initial_map, Map::kConstructorOrBackPointerOffset);
|
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(
|
Node* instance_size_words = ChangeUint32ToWord(LoadObjectField(
|
||||||
initial_map, Map::kInstanceSizeOffset, MachineType::Uint8()));
|
initial_map, Map::kInstanceSizeOffset, MachineType::Uint8()));
|
||||||
@ -214,7 +241,7 @@ TF_BUILTIN(FastNewObject, ConstructorBuiltinsAssembler) {
|
|||||||
Comment("no slack tracking");
|
Comment("no slack tracking");
|
||||||
InitializeFieldsWithRoot(object, IntPtrConstant(JSObject::kHeaderSize),
|
InitializeFieldsWithRoot(object, IntPtrConstant(JSObject::kHeaderSize),
|
||||||
instance_size, Heap::kUndefinedValueRootIndex);
|
instance_size, Heap::kUndefinedValueRootIndex);
|
||||||
Return(object);
|
Goto(&end);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -243,7 +270,7 @@ TF_BUILTIN(FastNewObject, ConstructorBuiltinsAssembler) {
|
|||||||
Comment("initialize undefined fields (no finalize)");
|
Comment("initialize undefined fields (no finalize)");
|
||||||
InitializeFieldsWithRoot(object, IntPtrConstant(JSObject::kHeaderSize),
|
InitializeFieldsWithRoot(object, IntPtrConstant(JSObject::kHeaderSize),
|
||||||
used_size, Heap::kUndefinedValueRootIndex);
|
used_size, Heap::kUndefinedValueRootIndex);
|
||||||
Return(object);
|
Goto(&end);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -265,8 +292,11 @@ TF_BUILTIN(FastNewObject, ConstructorBuiltinsAssembler) {
|
|||||||
used_size, Heap::kUndefinedValueRootIndex);
|
used_size, Heap::kUndefinedValueRootIndex);
|
||||||
|
|
||||||
CallRuntime(Runtime::kFinalizeInstanceSize, context, initial_map);
|
CallRuntime(Runtime::kFinalizeInstanceSize, context, initial_map);
|
||||||
Return(object);
|
Goto(&end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bind(&end);
|
||||||
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* ConstructorBuiltinsAssembler::EmitFastNewFunctionContext(
|
Node* ConstructorBuiltinsAssembler::EmitFastNewFunctionContext(
|
||||||
|
@ -44,6 +44,11 @@ class ConstructorBuiltinsAssembler : public CodeStubAssembler {
|
|||||||
Node* properties_count);
|
Node* properties_count);
|
||||||
void CreateFastCloneShallowObjectBuiltin(int 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:
|
private:
|
||||||
static const int kMaximumSlots = 0x8000;
|
static const int kMaximumSlots = 0x8000;
|
||||||
static const int kSmallMaximumSlots = 10;
|
static const int kSmallMaximumSlots = 10;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "src/builtins/builtins-promise.h"
|
#include "src/builtins/builtins-promise.h"
|
||||||
|
#include "src/builtins/builtins-constructor.h"
|
||||||
#include "src/builtins/builtins-utils.h"
|
#include "src/builtins/builtins-utils.h"
|
||||||
#include "src/builtins/builtins.h"
|
#include "src/builtins/builtins.h"
|
||||||
#include "src/code-factory.h"
|
#include "src/code-factory.h"
|
||||||
@ -742,9 +743,9 @@ TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) {
|
|||||||
|
|
||||||
Bind(&if_targetismodified);
|
Bind(&if_targetismodified);
|
||||||
{
|
{
|
||||||
Callable fast_new_object_stub = CodeFactory::FastNewObject(isolate);
|
ConstructorBuiltinsAssembler constructor_assembler(this->state());
|
||||||
Node* const instance =
|
Node* const instance = constructor_assembler.EmitFastNewObject(
|
||||||
CallStub(fast_new_object_stub, context, promise_fun, new_target);
|
context, promise_fun, new_target);
|
||||||
|
|
||||||
var_result.Bind(instance);
|
var_result.Bind(instance);
|
||||||
Goto(&init);
|
Goto(&init);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "src/builtins/builtins-constructor.h"
|
||||||
#include "src/builtins/builtins-utils.h"
|
#include "src/builtins/builtins-utils.h"
|
||||||
#include "src/builtins/builtins.h"
|
#include "src/builtins/builtins.h"
|
||||||
#include "src/code-factory.h"
|
#include "src/code-factory.h"
|
||||||
@ -786,9 +787,9 @@ TF_BUILTIN(RegExpConstructor, RegExpBuiltinsAssembler) {
|
|||||||
|
|
||||||
Bind(&allocate_generic);
|
Bind(&allocate_generic);
|
||||||
{
|
{
|
||||||
Callable fastnewobject_callable = CodeFactory::FastNewObject(isolate);
|
ConstructorBuiltinsAssembler constructor_assembler(this->state());
|
||||||
Node* const regexp = CallStub(fastnewobject_callable, context,
|
Node* const regexp = constructor_assembler.EmitFastNewObject(
|
||||||
regexp_function, var_new_target.value());
|
context, regexp_function, var_new_target.value());
|
||||||
var_regexp.Bind(regexp);
|
var_regexp.Bind(regexp);
|
||||||
Goto(&next);
|
Goto(&next);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user