Commit 4c41299d authored by Georg Neis's avatar Georg Neis Committed by V8 LUCI CQ

[compiler] Fix serialization for Function#bind

It was not in sync with the optimization, which relies on
inspecting up the length and name fields even for bound
functions.

To make a now meaningful serializer test actually pass, I have
to to make some changes to the test setup.

I'm also moving the function name and length index constants
from JSFunction to JSFunctionOrBoundFunction for clarity.

TBR=marja@chromium.org

Bug: v8:7790
Change-Id: I36dd3c80996ccb53810c7ea9bfceb5c84ffd60ab
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2972919
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarSantiago Aboy Solanes <solanes@chromium.org>
Reviewed-by: 's avatarDominik Inführ <dinfuehr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75299}
parent 332d6c11
......@@ -16,10 +16,10 @@ extern transitioning builtin
FunctionPrototypeBind(implicit context: Context)(
JSFunction, JSAny, int32): JSAny;
const kLengthDescriptorIndex:
constexpr int32 generates 'JSFunction::kLengthDescriptorIndex';
const kNameDescriptorIndex:
constexpr int32 generates 'JSFunction::kNameDescriptorIndex';
const kLengthDescriptorIndex: constexpr int32
generates 'JSFunctionOrBoundFunction::kLengthDescriptorIndex';
const kNameDescriptorIndex: constexpr int32
generates 'JSFunctionOrBoundFunction::kNameDescriptorIndex';
const kMinDescriptorsForFastBind:
constexpr int31 generates 'JSFunction::kMinDescriptorsForFastBind';
......
......@@ -34,7 +34,7 @@
#include "src/objects/feedback-vector-inl.h"
#include "src/objects/js-array-buffer-inl.h"
#include "src/objects/js-array-inl.h"
#include "src/objects/js-objects.h"
#include "src/objects/js-function.h"
#include "src/objects/objects-inl.h"
#include "src/objects/ordered-hash-table.h"
......@@ -2633,14 +2633,17 @@ Reduction JSCallReducer::ReduceFunctionPrototypeBind(Node* node) {
// recomputed even if the actual value of the object changes.
// This mirrors the checks done in builtins-function-gen.cc at
// runtime otherwise.
int minimum_nof_descriptors = std::max({JSFunction::kLengthDescriptorIndex,
JSFunction::kNameDescriptorIndex}) +
int minimum_nof_descriptors =
std::max({JSFunctionOrBoundFunction::kLengthDescriptorIndex,
JSFunctionOrBoundFunction::kNameDescriptorIndex}) +
1;
if (receiver_map.NumberOfOwnDescriptors() < minimum_nof_descriptors) {
return inference.NoChange();
}
const InternalIndex kLengthIndex(JSFunction::kLengthDescriptorIndex);
const InternalIndex kNameIndex(JSFunction::kNameDescriptorIndex);
const InternalIndex kLengthIndex(
JSFunctionOrBoundFunction::kLengthDescriptorIndex);
const InternalIndex kNameIndex(
JSFunctionOrBoundFunction::kNameDescriptorIndex);
if (!receiver_map.serialized_own_descriptor(kLengthIndex) ||
!receiver_map.serialized_own_descriptor(kNameIndex)) {
TRACE_BROKER_MISSING(broker(),
......
......@@ -2716,8 +2716,9 @@ void ProcessMapForFunctionBind(MapRef map) {
1;
if (map.NumberOfOwnDescriptors() >= min_nof_descriptors) {
map.SerializeOwnDescriptor(
InternalIndex(JSFunction::kLengthDescriptorIndex));
map.SerializeOwnDescriptor(InternalIndex(JSFunction::kNameDescriptorIndex));
InternalIndex(JSFunctionOrBoundFunction::kLengthDescriptorIndex));
map.SerializeOwnDescriptor(
InternalIndex(JSFunctionOrBoundFunction::kNameDescriptorIndex));
}
}
} // namespace
......@@ -2725,17 +2726,22 @@ void ProcessMapForFunctionBind(MapRef map) {
void SerializerForBackgroundCompilation::ProcessHintsForFunctionBind(
Hints const& receiver_hints) {
for (auto constant : receiver_hints.constants()) {
if (!constant->IsJSFunction()) continue;
if (constant->IsJSFunction()) {
JSFunctionRef function =
MakeRef(broker(), Handle<JSFunction>::cast(constant));
function.Serialize();
ProcessMapForFunctionBind(function.map());
} else if (constant->IsJSBoundFunction()) {
JSBoundFunctionRef function =
MakeRef(broker(), Handle<JSBoundFunction>::cast(constant));
function.Serialize();
ProcessMapForFunctionBind(function.map());
}
}
for (auto map : receiver_hints.maps()) {
if (!map->IsJSFunctionMap()) continue;
MapRef map_ref = MakeRef(broker(), map);
ProcessMapForFunctionBind(map_ref);
if (!map->IsJSFunctionMap() && !map->IsJSBoundFunctionMap()) continue;
ProcessMapForFunctionBind(MakeRef(broker(), map));
}
}
......
......@@ -3572,14 +3572,14 @@ Handle<Map> Factory::CreateSloppyFunctionMap(
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
int field_index = 0;
STATIC_ASSERT(JSFunction::kLengthDescriptorIndex == 0);
STATIC_ASSERT(JSFunctionOrBoundFunction::kLengthDescriptorIndex == 0);
{ // Add length accessor.
Descriptor d = Descriptor::AccessorConstant(
length_string(), function_length_accessor(), roc_attribs);
map->AppendDescriptor(isolate(), &d);
}
STATIC_ASSERT(JSFunction::kNameDescriptorIndex == 1);
STATIC_ASSERT(JSFunctionOrBoundFunction::kNameDescriptorIndex == 1);
if (IsFunctionModeWithName(function_mode)) {
// Add name field.
Handle<Name> name = isolate()->factory()->name_string();
......
......@@ -3871,6 +3871,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
Map::EnsureDescriptorSlack(isolate_, map, 2);
{ // length
STATIC_ASSERT(JSFunctionOrBoundFunction::kLengthDescriptorIndex == 0);
Descriptor d = Descriptor::AccessorConstant(
factory->length_string(), factory->bound_function_length_accessor(),
roc_attribs);
......@@ -3878,6 +3879,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
}
{ // name
STATIC_ASSERT(JSFunctionOrBoundFunction::kNameDescriptorIndex == 1);
Descriptor d = Descriptor::AccessorConstant(
factory->name_string(), factory->bound_function_name_accessor(),
roc_attribs);
......
......@@ -24,6 +24,9 @@ class JSFunctionOrBoundFunction
: public TorqueGeneratedJSFunctionOrBoundFunction<JSFunctionOrBoundFunction,
JSObject> {
public:
static const int kLengthDescriptorIndex = 0;
static const int kNameDescriptorIndex = 1;
STATIC_ASSERT(kHeaderSize == JSObject::kHeaderSize);
TQ_OBJECT_CONSTRUCTORS(JSFunctionOrBoundFunction)
};
......@@ -59,9 +62,6 @@ class JSFunction : public JSFunctionOrBoundFunction {
// can be shared by instances.
DECL_ACCESSORS(shared, SharedFunctionInfo)
static const int kLengthDescriptorIndex = 0;
static const int kNameDescriptorIndex = 1;
// Fast binding requires length and name accessors.
static const int kMinDescriptorsForFastBind = 2;
......
......@@ -272,6 +272,7 @@ i::Handle<i::JSFunction> Optimize(
i::OptimizedCompilationInfo info(zone, isolate, shared, function,
i::CodeKind::TURBOFAN);
if (flags & ~i::OptimizedCompilationInfo::kInlining) UNIMPLEMENTED();
if (flags & i::OptimizedCompilationInfo::kInlining) {
info.set_inlining();
}
......
This diff is collapsed.
......@@ -18,15 +18,16 @@ class ZoneStats;
// The purpose of this class is to provide testing facility for the
// SerializerForBackgroundCompilation class. On a high-level, it executes the
// following steps:
// 1. Wraps the provided source in an IIFE
// 2. Generates bytecode for the given source
// 3. Runs the bytecode which *must* return a function
// 4. Takes the returned function and optimizes it
// 5. The optimized function is accessible through `function()`
// code given by {global_source} at global scope and then performs the following
// steps for {local_source}:
// 1. Wraps it in an IIFE.
// 2. Generates bytecode and runs it, which *must* return a function.
// 3. Takes the returned function and optimizes it.
// 4. The optimized function is accessible through `function()`.
class SerializerTester : public HandleAndZoneScope {
public:
explicit SerializerTester(const char* source);
explicit SerializerTester(const char* global_source,
const char* local_source);
JSFunctionRef function() const { return function_.value(); }
JSHeapBroker* broker() const { return broker_.get(); }
......
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