Commit edbcb4b4 authored by Igor Sheludko's avatar Igor Sheludko Committed by Commit Bot

[csa] Support querying kJSTarget parameter in TFJ builtins.

Bug: v8:7754
Change-Id: I0c74b4025d9e52f3580e2da6bd7ac2b8ec2ee620
Reviewed-on: https://chromium-review.googlesource.com/1104469
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarDaniel Clifford <danno@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53969}
parent f2695f73
...@@ -1007,8 +1007,10 @@ TF_BUILTIN(ArrayPrototypePop, CodeStubAssembler) { ...@@ -1007,8 +1007,10 @@ TF_BUILTIN(ArrayPrototypePop, CodeStubAssembler) {
BIND(&runtime); BIND(&runtime);
{ {
Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset, // We are not using Parameter(Descriptor::kJSTarget) and loading the value
MachineType::TaggedPointer()); // from the current frame here in order to reduce register pressure on the
// fast path.
TNode<JSFunction> target = LoadTargetFromFrame();
TailCallBuiltin(Builtins::kArrayPop, context, target, UndefinedConstant(), TailCallBuiltin(Builtins::kArrayPop, context, target, UndefinedConstant(),
argc); argc);
} }
...@@ -1139,8 +1141,10 @@ TF_BUILTIN(ArrayPrototypePush, CodeStubAssembler) { ...@@ -1139,8 +1141,10 @@ TF_BUILTIN(ArrayPrototypePush, CodeStubAssembler) {
BIND(&runtime); BIND(&runtime);
{ {
Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset, // We are not using Parameter(Descriptor::kJSTarget) and loading the value
MachineType::TaggedPointer()); // from the current frame here in order to reduce register pressure on the
// fast path.
TNode<JSFunction> target = LoadTargetFromFrame();
TailCallBuiltin(Builtins::kArrayPush, context, target, UndefinedConstant(), TailCallBuiltin(Builtins::kArrayPush, context, target, UndefinedConstant(),
argc); argc);
} }
...@@ -1636,8 +1640,10 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) { ...@@ -1636,8 +1640,10 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) {
BIND(&runtime); BIND(&runtime);
{ {
Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset, // We are not using Parameter(Descriptor::kJSTarget) and loading the value
MachineType::TaggedPointer()); // from the current frame here in order to reduce register pressure on the
// fast path.
TNode<JSFunction> target = LoadTargetFromFrame();
TailCallBuiltin(Builtins::kArrayShift, context, target, UndefinedConstant(), TailCallBuiltin(Builtins::kArrayShift, context, target, UndefinedConstant(),
argc); argc);
} }
......
...@@ -28,8 +28,10 @@ TF_BUILTIN(FastConsoleAssert, CodeStubAssembler) { ...@@ -28,8 +28,10 @@ TF_BUILTIN(FastConsoleAssert, CodeStubAssembler) {
BIND(&runtime); BIND(&runtime);
{ {
Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset, // We are not using Parameter(Descriptor::kJSTarget) and loading the value
MachineType::TaggedPointer()); // from the current frame here in order to reduce register pressure on the
// fast path.
TNode<JSFunction> target = LoadTargetFromFrame();
TailCallBuiltin(Builtins::kConsoleAssert, context, target, new_target, TailCallBuiltin(Builtins::kConsoleAssert, context, target, new_target,
argc); argc);
} }
......
...@@ -640,8 +640,7 @@ TF_BUILTIN(ObjectConstructor, ConstructorBuiltinsAssembler) { ...@@ -640,8 +640,7 @@ TF_BUILTIN(ObjectConstructor, ConstructorBuiltinsAssembler) {
Label if_subclass(this, Label::kDeferred), if_notsubclass(this), Label if_subclass(this, Label::kDeferred), if_notsubclass(this),
return_result(this); return_result(this);
GotoIf(IsUndefined(new_target), &if_notsubclass); GotoIf(IsUndefined(new_target), &if_notsubclass);
Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset, TNode<JSFunction> target = CAST(Parameter(Descriptor::kJSTarget));
MachineType::TaggedPointer());
Branch(WordEqual(new_target, target), &if_notsubclass, &if_subclass); Branch(WordEqual(new_target, target), &if_notsubclass, &if_subclass);
BIND(&if_subclass); BIND(&if_subclass);
...@@ -718,8 +717,11 @@ TF_BUILTIN(NumberConstructor, ConstructorBuiltinsAssembler) { ...@@ -718,8 +717,11 @@ TF_BUILTIN(NumberConstructor, ConstructorBuiltinsAssembler) {
// "%NumberPrototype%", « [[NumberData]] »). // "%NumberPrototype%", « [[NumberData]] »).
// 5. Set O.[[NumberData]] to n. // 5. Set O.[[NumberData]] to n.
// 6. Return O. // 6. Return O.
Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset,
MachineType::TaggedPointer()); // We are not using Parameter(Descriptor::kJSTarget) and loading the value
// from the current frame here in order to reduce register pressure on the
// fast path.
TNode<JSFunction> target = LoadTargetFromFrame();
Node* result = Node* result =
CallBuiltin(Builtins::kFastNewObject, context, target, new_target); CallBuiltin(Builtins::kFastNewObject, context, target, new_target);
StoreObjectField(result, JSValue::kValueOffset, n_value); StoreObjectField(result, JSValue::kValueOffset, n_value);
...@@ -735,9 +737,7 @@ TF_BUILTIN(StringConstructor, ConstructorBuiltinsAssembler) { ...@@ -735,9 +737,7 @@ TF_BUILTIN(StringConstructor, ConstructorBuiltinsAssembler) {
ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
CodeStubArguments args(this, argc); CodeStubArguments args(this, argc);
Node* new_target = Parameter(Descriptor::kJSNewTarget); TNode<Object> new_target = CAST(Parameter(Descriptor::kJSNewTarget));
Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset,
MachineType::TaggedPointer());
// 1. If no arguments were passed to this function invocation, let s be "". // 1. If no arguments were passed to this function invocation, let s be "".
VARIABLE(var_s, MachineRepresentation::kTagged, EmptyStringConstant()); VARIABLE(var_s, MachineRepresentation::kTagged, EmptyStringConstant());
...@@ -778,6 +778,11 @@ TF_BUILTIN(StringConstructor, ConstructorBuiltinsAssembler) { ...@@ -778,6 +778,11 @@ TF_BUILTIN(StringConstructor, ConstructorBuiltinsAssembler) {
BIND(&constructstring); BIND(&constructstring);
{ {
// We are not using Parameter(Descriptor::kJSTarget) and loading the value
// from the current frame here in order to reduce register pressure on the
// fast path.
TNode<JSFunction> target = LoadTargetFromFrame();
Node* result = Node* result =
CallBuiltin(Builtins::kFastNewObject, context, target, new_target); CallBuiltin(Builtins::kFastNewObject, context, target, new_target);
StoreObjectField(result, JSValue::kValueOffset, s_value); StoreObjectField(result, JSValue::kValueOffset, s_value);
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define V8_BUILTINS_BUILTINS_DESCRIPTORS_H_ #define V8_BUILTINS_BUILTINS_DESCRIPTORS_H_
#include "src/builtins/builtins.h" #include "src/builtins/builtins.h"
#include "src/compiler/code-assembler.h"
#include "src/interface-descriptors.h" #include "src/interface-descriptors.h"
#include "src/objects/shared-function-info.h" #include "src/objects/shared-function-info.h"
...@@ -16,7 +17,7 @@ namespace internal { ...@@ -16,7 +17,7 @@ namespace internal {
#define DEFINE_TFJ_INTERFACE_DESCRIPTOR(Name, Argc, ...) \ #define DEFINE_TFJ_INTERFACE_DESCRIPTOR(Name, Argc, ...) \
struct Builtin_##Name##_InterfaceDescriptor { \ struct Builtin_##Name##_InterfaceDescriptor { \
enum ParameterIndices { \ enum ParameterIndices { \
kJSTarget = -1, \ kJSTarget = compiler::CodeAssembler::kTargetParameterIndex, \
##__VA_ARGS__, \ ##__VA_ARGS__, \
kJSNewTarget, \ kJSNewTarget, \
kJSActualArgumentsCount, \ kJSActualArgumentsCount, \
...@@ -25,6 +26,7 @@ namespace internal { ...@@ -25,6 +26,7 @@ namespace internal {
}; \ }; \
static_assert((Argc) == static_cast<uint16_t>(kParameterCount - 4), \ static_assert((Argc) == static_cast<uint16_t>(kParameterCount - 4), \
"Inconsistent set of arguments"); \ "Inconsistent set of arguments"); \
static_assert(kJSTarget == -1, "Unexpected kJSTarget index value"); \
}; };
// Define interface descriptors for builtins with StubCall linkage. // Define interface descriptors for builtins with StubCall linkage.
......
...@@ -184,10 +184,14 @@ TF_BUILTIN(FastFunctionPrototypeBind, CodeStubAssembler) { ...@@ -184,10 +184,14 @@ TF_BUILTIN(FastFunctionPrototypeBind, CodeStubAssembler) {
} }
BIND(&slow); BIND(&slow);
Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset, {
MachineType::TaggedPointer()); // We are not using Parameter(Descriptor::kJSTarget) and loading the value
TailCallBuiltin(Builtins::kFunctionPrototypeBind, context, target, new_target, // from the current frame here in order to reduce register pressure on the
argc); // fast path.
TNode<JSFunction> target = LoadTargetFromFrame();
TailCallBuiltin(Builtins::kFunctionPrototypeBind, context, target,
new_target, argc);
}
} }
// ES6 #sec-function.prototype-@@hasinstance // ES6 #sec-function.prototype-@@hasinstance
......
...@@ -180,8 +180,7 @@ TF_BUILTIN(DebugBreakTrampoline, CodeStubAssembler) { ...@@ -180,8 +180,7 @@ TF_BUILTIN(DebugBreakTrampoline, CodeStubAssembler) {
TNode<Object> new_target = CAST(Parameter(Descriptor::kJSNewTarget)); TNode<Object> new_target = CAST(Parameter(Descriptor::kJSNewTarget));
TNode<Int32T> arg_count = TNode<Int32T> arg_count =
UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount)); UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount));
TNode<JSFunction> function = CAST(LoadFromFrame( TNode<JSFunction> function = CAST(Parameter(Descriptor::kJSTarget));
StandardFrameConstants::kFunctionOffset, MachineType::TaggedPointer()));
// Check break-at-entry flag on the debug info. // Check break-at-entry flag on the debug info.
TNode<SharedFunctionInfo> shared = TNode<SharedFunctionInfo> shared =
......
...@@ -2028,7 +2028,7 @@ TF_BUILTIN(PromiseAll, PromiseBuiltinsAssembler) { ...@@ -2028,7 +2028,7 @@ TF_BUILTIN(PromiseAll, PromiseBuiltinsAssembler) {
TF_BUILTIN(PromiseAllResolveElementClosure, PromiseBuiltinsAssembler) { TF_BUILTIN(PromiseAllResolveElementClosure, PromiseBuiltinsAssembler) {
TNode<Object> value = CAST(Parameter(Descriptor::kValue)); TNode<Object> value = CAST(Parameter(Descriptor::kValue));
TNode<Context> context = CAST(Parameter(Descriptor::kContext)); TNode<Context> context = CAST(Parameter(Descriptor::kContext));
Node* function = LoadFromFrame(StandardFrameConstants::kFunctionOffset); TNode<JSFunction> function = CAST(Parameter(Descriptor::kJSTarget));
Label already_called(this, Label::kDeferred), resolve_promise(this); Label already_called(this, Label::kDeferred), resolve_promise(this);
......
...@@ -757,10 +757,9 @@ TF_BUILTIN(TypedArrayConstructorLazyDeoptContinuation, ...@@ -757,10 +757,9 @@ TF_BUILTIN(TypedArrayConstructorLazyDeoptContinuation,
// ES #sec-typedarray-constructors // ES #sec-typedarray-constructors
TF_BUILTIN(TypedArrayConstructor, TypedArrayBuiltinsAssembler) { TF_BUILTIN(TypedArrayConstructor, TypedArrayBuiltinsAssembler) {
Node* context = Parameter(Descriptor::kContext); TNode<Context> context = CAST(Parameter(Descriptor::kContext));
Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset, TNode<JSFunction> target = CAST(Parameter(Descriptor::kJSTarget));
MachineType::TaggedPointer()); TNode<Object> new_target = CAST(Parameter(Descriptor::kJSNewTarget));
Node* new_target = Parameter(Descriptor::kJSNewTarget);
Node* argc = Node* argc =
ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
CodeStubArguments args(this, argc); CodeStubArguments args(this, argc);
......
...@@ -1337,6 +1337,12 @@ Node* CodeStubAssembler::LoadFromParentFrame(int offset, MachineType rep) { ...@@ -1337,6 +1337,12 @@ Node* CodeStubAssembler::LoadFromParentFrame(int offset, MachineType rep) {
return Load(rep, frame_pointer, IntPtrConstant(offset)); return Load(rep, frame_pointer, IntPtrConstant(offset));
} }
TNode<JSFunction> CodeStubAssembler::LoadTargetFromFrame() {
DCHECK(IsJSFunctionCall());
return CAST(LoadFromFrame(StandardFrameConstants::kFunctionOffset,
MachineType::TaggedPointer()));
}
Node* CodeStubAssembler::LoadBufferObject(Node* buffer, int offset, Node* CodeStubAssembler::LoadBufferObject(Node* buffer, int offset,
MachineType rep) { MachineType rep) {
return Load(rep, buffer, IntPtrConstant(offset)); return Load(rep, buffer, IntPtrConstant(offset));
......
...@@ -727,6 +727,14 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -727,6 +727,14 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* LoadFromParentFrame(int offset, Node* LoadFromParentFrame(int offset,
MachineType rep = MachineType::AnyTagged()); MachineType rep = MachineType::AnyTagged());
// Load target function from the current JS frame.
// This is an alternative way of getting the target function in addition to
// Parameter(Descriptor::kJSTarget). The latter should be used near the
// beginning of builtin code while the target value is still in the register
// and the former should be used in slow paths in order to reduce register
// pressure on the fast path.
TNode<JSFunction> LoadTargetFromFrame();
// Load an object pointer from a buffer that isn't in the heap. // Load an object pointer from a buffer that isn't in the heap.
Node* LoadBufferObject(Node* buffer, int offset, Node* LoadBufferObject(Node* buffer, int offset,
MachineType rep = MachineType::AnyTagged()); MachineType rep = MachineType::AnyTagged());
......
...@@ -371,8 +371,14 @@ bool CodeAssembler::IsNullConstant(TNode<Object> node) { ...@@ -371,8 +371,14 @@ bool CodeAssembler::IsNullConstant(TNode<Object> node) {
return m.Is(isolate()->factory()->null_value()); return m.Is(isolate()->factory()->null_value());
} }
Node* CodeAssembler::Parameter(int value) { Node* CodeAssembler::Parameter(int index) {
return raw_assembler()->Parameter(value); if (index == kTargetParameterIndex) return raw_assembler()->TargetParameter();
return raw_assembler()->Parameter(index);
}
bool CodeAssembler::IsJSFunctionCall() const {
auto call_descriptor = raw_assembler()->call_descriptor();
return call_descriptor->IsJSFunctionCall();
} }
TNode<Context> CodeAssembler::GetJSContextParameter() { TNode<Context> CodeAssembler::GetJSContextParameter() {
......
...@@ -738,6 +738,8 @@ class V8_EXPORT_PRIVATE CodeAssembler { ...@@ -738,6 +738,8 @@ class V8_EXPORT_PRIVATE CodeAssembler {
return UncheckedCast<UintPtrT>(x); return UncheckedCast<UintPtrT>(x);
} }
static constexpr int kTargetParameterIndex = -1;
Node* Parameter(int value); Node* Parameter(int value);
TNode<Context> GetJSContextParameter(); TNode<Context> GetJSContextParameter();
...@@ -1197,6 +1199,8 @@ class V8_EXPORT_PRIVATE CodeAssembler { ...@@ -1197,6 +1199,8 @@ class V8_EXPORT_PRIVATE CodeAssembler {
bool Word32ShiftIsSafe() const; bool Word32ShiftIsSafe() const;
PoisoningMitigationLevel poisoning_level() const; PoisoningMitigationLevel poisoning_level() const;
bool IsJSFunctionCall() const;
private: private:
TNode<Object> CallRuntimeImpl(Runtime::FunctionId function, TNode<Object> CallRuntimeImpl(Runtime::FunctionId function,
TNode<Object> context, TNode<Object> context,
......
...@@ -24,12 +24,17 @@ RawMachineAssembler::RawMachineAssembler( ...@@ -24,12 +24,17 @@ RawMachineAssembler::RawMachineAssembler(
machine_(zone(), word, flags, alignment_requirements), machine_(zone(), word, flags, alignment_requirements),
common_(zone()), common_(zone()),
call_descriptor_(call_descriptor), call_descriptor_(call_descriptor),
target_parameter_(nullptr),
parameters_(parameter_count(), zone()), parameters_(parameter_count(), zone()),
current_block_(schedule()->start()), current_block_(schedule()->start()),
poisoning_level_(poisoning_level) { poisoning_level_(poisoning_level) {
int param_count = static_cast<int>(parameter_count()); int param_count = static_cast<int>(parameter_count());
// Add an extra input for the JSFunction parameter to the start node. // Add an extra input for the JSFunction parameter to the start node.
graph->SetStart(graph->NewNode(common_.Start(param_count + 1))); graph->SetStart(graph->NewNode(common_.Start(param_count + 1)));
if (call_descriptor->IsJSFunctionCall()) {
target_parameter_ = AddNode(
common()->Parameter(Linkage::kJSCallClosureParamIndex), graph->start());
}
for (size_t i = 0; i < parameter_count(); ++i) { for (size_t i = 0; i < parameter_count(); ++i) {
parameters_[i] = parameters_[i] =
AddNode(common()->Parameter(static_cast<int>(i)), graph->start()); AddNode(common()->Parameter(static_cast<int>(i)), graph->start());
...@@ -72,6 +77,10 @@ Schedule* RawMachineAssembler::Export() { ...@@ -72,6 +77,10 @@ Schedule* RawMachineAssembler::Export() {
return schedule; return schedule;
} }
Node* RawMachineAssembler::TargetParameter() {
DCHECK_NOT_NULL(target_parameter_);
return target_parameter_;
}
Node* RawMachineAssembler::Parameter(size_t index) { Node* RawMachineAssembler::Parameter(size_t index) {
DCHECK(index < parameter_count()); DCHECK(index < parameter_count());
......
...@@ -742,6 +742,7 @@ class V8_EXPORT_PRIVATE RawMachineAssembler { ...@@ -742,6 +742,7 @@ class V8_EXPORT_PRIVATE RawMachineAssembler {
} }
// Parameters. // Parameters.
Node* TargetParameter();
Node* Parameter(size_t index); Node* Parameter(size_t index);
// Pointer utilities. // Pointer utilities.
...@@ -936,6 +937,7 @@ class V8_EXPORT_PRIVATE RawMachineAssembler { ...@@ -936,6 +937,7 @@ class V8_EXPORT_PRIVATE RawMachineAssembler {
MachineOperatorBuilder machine_; MachineOperatorBuilder machine_;
CommonOperatorBuilder common_; CommonOperatorBuilder common_;
CallDescriptor* call_descriptor_; CallDescriptor* call_descriptor_;
Node* target_parameter_;
NodeVector parameters_; NodeVector parameters_;
BasicBlock* current_block_; BasicBlock* current_block_;
PoisoningMitigationLevel poisoning_level_; PoisoningMitigationLevel poisoning_level_;
......
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