Commit 455f9df0 authored by danno's avatar danno Committed by Commit bot

[turbofan] Reland: Avoid going through ArgumentsAdaptorTrampoline for select CSA array builtins

This CL changes certain frequently-called Array builtins to use CodeStubArguments
rather than peek at the stack frames above array builtins to determine if options
arguments have been passed into them.

Previous failure likely due to unfortunate/unluckily timed GC that moved due to
changed timing/allocation from this CL. Test mitigation for allocation-site-info.js
included.

BUG=v8:1956
LOG=N

Review-Url: https://codereview.chromium.org/2829093004
Cr-Commit-Position: refs/heads/master@{#44998}
parent 6953bb40
......@@ -177,7 +177,8 @@ class Genesis BASE_EMBEDDED {
#undef DECLARE_FEATURE_INITIALIZATION
void InstallOneBuiltinFunction(Handle<Object> prototype, const char* method,
Builtins::Name name);
Builtins::Name name,
int internal_formal_parameter_count);
void InitializeGlobal_experimental_fast_array_builtins();
Handle<JSFunction> InstallArrayBuffer(Handle<JSObject> target,
......@@ -3862,15 +3863,17 @@ void InstallPublicSymbol(Factory* factory, Handle<Context> native_context,
void Genesis::InstallOneBuiltinFunction(Handle<Object> prototype,
const char* method_name,
Builtins::Name builtin_name) {
Builtins::Name builtin_name,
int internal_formal_parameter_count) {
LookupIterator it(
prototype, isolate()->factory()->NewStringFromAsciiChecked(method_name),
LookupIterator::OWN_SKIP_INTERCEPTOR);
Handle<Object> function = Object::GetProperty(&it).ToHandleChecked();
Handle<JSFunction>::cast(function)->set_code(
isolate()->builtins()->builtin(builtin_name));
Handle<JSFunction>::cast(function)->shared()->set_code(
isolate()->builtins()->builtin(builtin_name));
SharedFunctionInfo* info = Handle<JSFunction>::cast(function)->shared();
info->set_code(isolate()->builtins()->builtin(builtin_name));
info->set_internal_formal_parameter_count(internal_formal_parameter_count);
}
void Genesis::InitializeGlobal_experimental_fast_array_builtins() {
......@@ -3880,13 +3883,17 @@ void Genesis::InitializeGlobal_experimental_fast_array_builtins() {
native_context()->typed_array_prototype(), isolate());
// Insert experimental fast TypedArray builtins here.
InstallOneBuiltinFunction(typed_array_prototype, "every",
Builtins::kTypedArrayPrototypeEvery);
Builtins::kTypedArrayPrototypeEvery,
SharedFunctionInfo::kDontAdaptArgumentsSentinel);
InstallOneBuiltinFunction(typed_array_prototype, "some",
Builtins::kTypedArrayPrototypeSome);
Builtins::kTypedArrayPrototypeSome,
SharedFunctionInfo::kDontAdaptArgumentsSentinel);
InstallOneBuiltinFunction(typed_array_prototype, "reduce",
Builtins::kTypedArrayPrototypeReduce);
Builtins::kTypedArrayPrototypeReduce,
SharedFunctionInfo::kDontAdaptArgumentsSentinel);
InstallOneBuiltinFunction(typed_array_prototype, "reduceRight",
Builtins::kTypedArrayPrototypeReduceRight);
Builtins::kTypedArrayPrototypeReduceRight,
SharedFunctionInfo::kDontAdaptArgumentsSentinel);
}
}
......@@ -4352,28 +4359,40 @@ bool Genesis::InstallNatives(GlobalContextType context_type) {
// Install Array.prototype.forEach
Handle<JSFunction> forEach = InstallArrayBuiltinFunction(
proto, "forEach", Builtins::kArrayForEach, 2);
proto, "forEach", Builtins::kArrayForEach,
SharedFunctionInfo::kDontAdaptArgumentsSentinel);
// Add forEach to the context.
native_context()->set_array_for_each_iterator(*forEach);
// Install Array.prototype.filter
InstallArrayBuiltinFunction(proto, "filter", Builtins::kArrayFilter, 2);
InstallArrayBuiltinFunction(
proto, "filter", Builtins::kArrayFilter,
SharedFunctionInfo::kDontAdaptArgumentsSentinel);
// Install Array.prototype.map
InstallArrayBuiltinFunction(proto, "map", Builtins::kArrayMap, 2);
InstallArrayBuiltinFunction(
proto, "map", Builtins::kArrayMap,
SharedFunctionInfo::kDontAdaptArgumentsSentinel);
// Install Array.prototype.every
InstallArrayBuiltinFunction(proto, "every", Builtins::kArrayEvery, 2);
InstallArrayBuiltinFunction(
proto, "every", Builtins::kArrayEvery,
SharedFunctionInfo::kDontAdaptArgumentsSentinel);
// Install Array.prototype.some
InstallArrayBuiltinFunction(proto, "some", Builtins::kArraySome, 2);
InstallArrayBuiltinFunction(
proto, "some", Builtins::kArraySome,
SharedFunctionInfo::kDontAdaptArgumentsSentinel);
// Install Array.prototype.reduce
InstallArrayBuiltinFunction(proto, "reduce", Builtins::kArrayReduce, 2);
InstallArrayBuiltinFunction(
proto, "reduce", Builtins::kArrayReduce,
SharedFunctionInfo::kDontAdaptArgumentsSentinel);
// Install Array.prototype.reduceRight
InstallArrayBuiltinFunction(proto, "reduceRight",
Builtins::kArrayReduceRight, 2);
InstallArrayBuiltinFunction(
proto, "reduceRight", Builtins::kArrayReduceRight,
SharedFunctionInfo::kDontAdaptArgumentsSentinel);
}
// Install InternalArray.prototype.concat
......
This diff is collapsed.
......@@ -269,33 +269,33 @@ namespace internal {
/* ES6 #sec-array.prototype.unshift */ \
CPP(ArrayUnshift) \
/* ES6 #sec-array.prototype.foreach */ \
TFJ(ArrayForEachLoopContinuation, 7, kCallbackFn, kThisArg, kArray, kObject, \
kInitialK, kLength, kTo) \
TFJ(ArrayForEach, 2, kCallbackFn, kThisArg) \
TFS(ArrayForEachLoopContinuation, kReceiver, kCallbackFn, kThisArg, kArray, \
kObject, kInitialK, kLength, kTo) \
TFJ(ArrayForEach, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.every */ \
TFJ(ArrayEveryLoopContinuation, 7, kCallbackFn, kThisArg, kArray, kObject, \
kInitialK, kLength, kTo) \
TFJ(ArrayEvery, 2, kCallbackFn, kThisArg) \
TFS(ArrayEveryLoopContinuation, kReceiver, kCallbackFn, kThisArg, kArray, \
kObject, kInitialK, kLength, kTo) \
TFJ(ArrayEvery, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.some */ \
TFJ(ArraySomeLoopContinuation, 7, kCallbackFn, kThisArg, kArray, kObject, \
kInitialK, kLength, kTo) \
TFJ(ArraySome, 2, kCallbackFn, kThisArg) \
TFS(ArraySomeLoopContinuation, kReceiver, kCallbackFn, kThisArg, kArray, \
kObject, kInitialK, kLength, kTo) \
TFJ(ArraySome, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.filter */ \
TFJ(ArrayFilterLoopContinuation, 7, kCallbackFn, kThisArg, kArray, kObject, \
kInitialK, kLength, kTo) \
TFJ(ArrayFilter, 2, kCallbackFn, kThisArg) \
TFS(ArrayFilterLoopContinuation, kReceiver, kCallbackFn, kThisArg, kArray, \
kObject, kInitialK, kLength, kTo) \
TFJ(ArrayFilter, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.foreach */ \
TFJ(ArrayMapLoopContinuation, 7, kCallbackFn, kThisArg, kArray, kObject, \
kInitialK, kLength, kTo) \
TFJ(ArrayMap, 2, kCallbackFn, kThisArg) \
/* ES6 #sec-array.prototype.reduce */ \
TFJ(ArrayReduceLoopContinuation, 7, kCallbackFn, kThisArg, kAccumulator, \
TFS(ArrayMapLoopContinuation, kReceiver, kCallbackFn, kThisArg, kArray, \
kObject, kInitialK, kLength, kTo) \
TFJ(ArrayReduce, 2, kCallbackFn, kInitialValue) \
TFJ(ArrayMap, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.reduce */ \
TFS(ArrayReduceLoopContinuation, kReceiver, kCallbackFn, kThisArg, \
kAccumulator, kObject, kInitialK, kLength, kTo) \
TFJ(ArrayReduce, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.reduceRight */ \
TFJ(ArrayReduceRightLoopContinuation, 7, kCallbackFn, kThisArg, \
TFS(ArrayReduceRightLoopContinuation, kReceiver, kCallbackFn, kThisArg, \
kAccumulator, kObject, kInitialK, kLength, kTo) \
TFJ(ArrayReduceRight, 2, kCallbackFn, kInitialValue) \
TFJ(ArrayReduceRight, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.entries */ \
TFJ(ArrayPrototypeEntries, 0) \
/* ES6 #sec-array.prototype.keys */ \
......@@ -935,13 +935,17 @@ namespace internal {
/* ES6 #sec-%typedarray%.prototype.slice */ \
CPP(TypedArrayPrototypeSlice) \
/* ES6 %TypedArray%.prototype.every */ \
TFJ(TypedArrayPrototypeEvery, 2, kCallbackFn, kThisArg) \
TFJ(TypedArrayPrototypeEvery, \
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 %TypedArray%.prototype.some */ \
TFJ(TypedArrayPrototypeSome, 2, kCallbackFn, kThisArg) \
TFJ(TypedArrayPrototypeSome, \
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 %TypedArray%.prototype.reduce */ \
TFJ(TypedArrayPrototypeReduce, 2, kCallbackFn, kInitialValue) \
TFJ(TypedArrayPrototypeReduce, \
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 %TypedArray%.prototype.reduceRight */ \
TFJ(TypedArrayPrototypeReduceRight, 2, kCallbackFn, kInitialValue) \
TFJ(TypedArrayPrototypeReduceRight, \
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
\
/* Wasm */ \
ASM(WasmCompileLazy) \
......
......@@ -504,48 +504,6 @@ Callable CodeFactory::ArrayPush(Isolate* isolate) {
return Callable(isolate->builtins()->ArrayPush(), BuiltinDescriptor(isolate));
}
// static
Callable CodeFactory::ArrayFilterLoopContinuation(Isolate* isolate) {
return Callable(isolate->builtins()->ArrayFilterLoopContinuation(),
IteratingArrayBuiltinLoopContinuationDescriptor(isolate));
}
// static
Callable CodeFactory::ArrayMapLoopContinuation(Isolate* isolate) {
return Callable(isolate->builtins()->ArrayMapLoopContinuation(),
IteratingArrayBuiltinLoopContinuationDescriptor(isolate));
}
// static
Callable CodeFactory::ArrayForEachLoopContinuation(Isolate* isolate) {
return Callable(isolate->builtins()->ArrayForEachLoopContinuation(),
IteratingArrayBuiltinLoopContinuationDescriptor(isolate));
}
// static
Callable CodeFactory::ArraySomeLoopContinuation(Isolate* isolate) {
return Callable(isolate->builtins()->ArraySomeLoopContinuation(),
IteratingArrayBuiltinLoopContinuationDescriptor(isolate));
}
// static
Callable CodeFactory::ArrayEveryLoopContinuation(Isolate* isolate) {
return Callable(isolate->builtins()->ArrayEveryLoopContinuation(),
IteratingArrayBuiltinLoopContinuationDescriptor(isolate));
}
// static
Callable CodeFactory::ArrayReduceLoopContinuation(Isolate* isolate) {
return Callable(isolate->builtins()->ArrayReduceLoopContinuation(),
IteratingArrayBuiltinLoopContinuationDescriptor(isolate));
}
// static
Callable CodeFactory::ArrayReduceRightLoopContinuation(Isolate* isolate) {
return Callable(isolate->builtins()->ArrayReduceRightLoopContinuation(),
IteratingArrayBuiltinLoopContinuationDescriptor(isolate));
}
// static
Callable CodeFactory::FunctionPrototypeBind(Isolate* isolate) {
return Callable(isolate->builtins()->FunctionPrototypeBind(),
......
......@@ -183,13 +183,6 @@ class V8_EXPORT_PRIVATE CodeFactory final {
static Callable ArrayConstructor(Isolate* isolate);
static Callable ArrayPush(Isolate* isolate);
static Callable ArrayFilterLoopContinuation(Isolate* isolate);
static Callable ArrayMapLoopContinuation(Isolate* isolate);
static Callable ArrayForEachLoopContinuation(Isolate* isolate);
static Callable ArraySomeLoopContinuation(Isolate* isolate);
static Callable ArrayEveryLoopContinuation(Isolate* isolate);
static Callable ArrayReduceLoopContinuation(Isolate* isolate);
static Callable ArrayReduceRightLoopContinuation(Isolate* isolate);
static Callable FunctionPrototypeBind(Isolate* isolate);
static Callable PromiseHandleReject(Isolate* isolate);
......
......@@ -8706,6 +8706,28 @@ Node* CodeStubArguments::AtIndex(int index) const {
return AtIndex(assembler_->IntPtrConstant(index));
}
Node* CodeStubArguments::GetOptionalArgumentValue(int index,
Node* default_value) {
typedef CodeStubAssembler::Variable Variable;
Variable result(assembler_, MachineRepresentation::kTagged);
CodeStubAssembler::Label argument_missing(assembler_),
argument_done(assembler_, &result);
assembler_->GotoIf(assembler_->UintPtrOrSmiGreaterThanOrEqual(
assembler_->IntPtrOrSmiConstant(index, argc_mode_),
argc_, argc_mode_),
&argument_missing);
result.Bind(AtIndex(index));
assembler_->Goto(&argument_done);
assembler_->BIND(&argument_missing);
result.Bind(default_value);
assembler_->Goto(&argument_done);
assembler_->BIND(&argument_done);
return result.value();
}
void CodeStubArguments::ForEach(
const CodeStubAssembler::VariableList& vars,
const CodeStubArguments::ForEachBodyFunction& body, Node* first, Node* last,
......
......@@ -1468,11 +1468,12 @@ class CodeStubArguments {
public:
typedef compiler::Node Node;
// |argc| is an uint32 value which specifies the number of arguments passed
// |argc| is an intptr value which specifies the number of arguments passed
// to the builtin excluding the receiver.
CodeStubArguments(CodeStubAssembler* assembler, Node* argc)
: CodeStubArguments(assembler, argc, nullptr,
CodeStubAssembler::INTPTR_PARAMETERS) {}
// |argc| is either a smi or intptr depending on |param_mode|
CodeStubArguments(CodeStubAssembler* assembler, Node* argc, Node* fp,
CodeStubAssembler::ParameterMode param_mode);
......@@ -1487,6 +1488,8 @@ class CodeStubArguments {
Node* AtIndex(int index) const;
Node* GetOptionalArgumentValue(int index, Node* default_value);
Node* GetLength() const { return argc_; }
typedef std::function<void(Node* arg)> ForEachBodyFunction;
......
......@@ -639,7 +639,7 @@ Node* CodeAssembler::CallStubR(const CallInterfaceDescriptor& descriptor,
#define INSTANTIATE(...) \
template V8_EXPORT_PRIVATE Node* CodeAssembler::CallStubR( \
const CallInterfaceDescriptor& descriptor, size_t, Node*, __VA_ARGS__);
REPEAT_1_TO_8(INSTANTIATE, Node*)
REPEAT_1_TO_11(INSTANTIATE, Node*)
#undef INSTANTIATE
Node* CodeAssembler::CallStubN(const CallInterfaceDescriptor& descriptor,
......
......@@ -54,7 +54,6 @@ class PlatformInterfaceDescriptor;
V(Builtin) \
V(ArrayConstructor) \
V(IteratingArrayBuiltin) \
V(IteratingArrayBuiltinLoopContinuation) \
V(ArrayNoArgumentConstructor) \
V(ArraySingleArgumentConstructor) \
V(ArrayNArgumentsConstructor) \
......@@ -226,12 +225,22 @@ class V8_EXPORT_PRIVATE CallInterfaceDescriptor {
} \
static inline CallDescriptors::Key key();
static const int kMaxBuiltinRegisterParams = 5;
#define DECLARE_DEFAULT_DESCRIPTOR(name, base, parameter_count) \
DECLARE_DESCRIPTOR_WITH_BASE(name, base) \
protected: \
static const int kRegisterParams = \
parameter_count > kMaxBuiltinRegisterParams ? kMaxBuiltinRegisterParams \
: parameter_count; \
static const int kStackParams = parameter_count - kRegisterParams; \
void InitializePlatformSpecific(CallInterfaceDescriptorData* data) \
override { \
DefaultInitializePlatformSpecific(data, parameter_count); \
DefaultInitializePlatformSpecific(data, kRegisterParams); \
} \
void InitializePlatformIndependent(CallInterfaceDescriptorData* data) \
override { \
data->InitializePlatformIndependent(kRegisterParams, kStackParams, NULL); \
} \
name(Isolate* isolate, CallDescriptors::Key key) : base(isolate, key) {} \
\
......@@ -642,14 +651,6 @@ class IteratingArrayBuiltinDescriptor : public BuiltinDescriptor {
DECLARE_BUILTIN_DESCRIPTOR(IteratingArrayBuiltinDescriptor)
};
class IteratingArrayBuiltinLoopContinuationDescriptor
: public BuiltinDescriptor {
public:
DEFINE_BUILTIN_PARAMETERS(kCallback, kThisArg, kArray, kObject, kInitialK,
kLength, kTo)
DECLARE_BUILTIN_DESCRIPTOR(IteratingArrayBuiltinLoopContinuationDescriptor)
};
class ArrayConstructorDescriptor : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kTarget, kNewTarget, kActualArgumentsCount, kAllocationSite)
......
......@@ -360,6 +360,12 @@ assertOptimized(instanceof_check);
instanceof_check(realmBArray);
assertUnoptimized(instanceof_check);
// Perform a gc because without it the test below can experience an
// allocation failure at an inconvenient point. Allocation mementos get
// cleared on gc, and they can't deliver elements kind feedback when that
// happens.
gc();
// Case: make sure nested arrays benefit from allocation site feedback as
// well.
(function() {
......
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
var a = [0];
function bar(x) { return x; }
function foo() { return a.reduce(bar); }
assertEquals(0, foo());
assertEquals(0, foo());
%OptimizeFunctionOnNextCall(foo);
assertEquals(0, foo());
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