Bring back the js-function-inl.h inline header

This is a manual revert of 67cdacd. Experiments have shown that inline
headers do bring real benefits and we won't be proceeding with inline
header removal.

Bug: v8:10749
Change-Id: Icd3d0b3926d0b7a24edb19d9f177e9c8818abe09
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2412174
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#69915}
This commit is contained in:
Jakob Gruber 2020-09-15 15:33:15 +02:00 committed by Commit Bot
parent 64610bda59
commit c417a08d02
12 changed files with 356 additions and 372 deletions

View File

@ -1063,6 +1063,7 @@ action("postmortem-metadata") {
"src/objects/js-array-buffer-inl.h",
"src/objects/js-array.h",
"src/objects/js-array-inl.h",
"src/objects/js-function-inl.h",
"src/objects/js-function.cc",
"src/objects/js-function.h",
"src/objects/js-objects.cc",
@ -2874,6 +2875,7 @@ v8_source_set("v8_base_without_compiler") {
"src/objects/js-display-names-inl.h",
"src/objects/js-display-names.cc",
"src/objects/js-display-names.h",
"src/objects/js-function-inl.h",
"src/objects/js-function.cc",
"src/objects/js-function.h",
"src/objects/js-generator-inl.h",

View File

@ -40,6 +40,7 @@
#include "src/interpreter/interpreter.h"
#include "src/logging/log-inl.h"
#include "src/objects/feedback-cell-inl.h"
#include "src/objects/js-function-inl.h"
#include "src/objects/map.h"
#include "src/objects/object-list-macros.h"
#include "src/objects/shared-function-info.h"

View File

@ -8,6 +8,7 @@
#include "src/execution/protectors.h"
#include "src/handles/handles-inl.h"
#include "src/objects/allocation-site-inl.h"
#include "src/objects/js-function-inl.h"
#include "src/objects/objects-inl.h"
#include "src/zone/zone-handle-set.h"

View File

@ -9,6 +9,7 @@
#include "src/objects/contexts.h"
#include "src/objects/dictionary-inl.h"
#include "src/objects/fixed-array-inl.h"
#include "src/objects/js-function-inl.h"
#include "src/objects/js-objects-inl.h"
#include "src/objects/map-inl.h"
#include "src/objects/objects-inl.h"

View File

@ -0,0 +1,304 @@
// Copyright 2020 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.
#ifndef V8_OBJECTS_JS_FUNCTION_INL_H_
#define V8_OBJECTS_JS_FUNCTION_INL_H_
#include "src/codegen/compiler.h"
#include "src/diagnostics/code-tracer.h"
#include "src/heap/heap-inl.h"
#include "src/ic/ic.h"
#include "src/init/bootstrapper.h"
#include "src/objects/feedback-cell-inl.h"
#include "src/objects/js-function.h"
#include "src/strings/string-builder-inl.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
TQ_OBJECT_CONSTRUCTORS_IMPL(JSFunctionOrBoundFunction)
TQ_OBJECT_CONSTRUCTORS_IMPL(JSBoundFunction)
OBJECT_CONSTRUCTORS_IMPL(JSFunction, JSFunctionOrBoundFunction)
CAST_ACCESSOR(JSFunction)
ACCESSORS(JSFunction, raw_feedback_cell, FeedbackCell, kFeedbackCellOffset)
FeedbackVector JSFunction::feedback_vector() const {
DCHECK(has_feedback_vector());
return FeedbackVector::cast(raw_feedback_cell().value());
}
ClosureFeedbackCellArray JSFunction::closure_feedback_cell_array() const {
DCHECK(has_closure_feedback_cell_array());
return ClosureFeedbackCellArray::cast(raw_feedback_cell().value());
}
bool JSFunction::HasOptimizationMarker() {
return has_feedback_vector() && feedback_vector().has_optimization_marker();
}
void JSFunction::ClearOptimizationMarker() {
DCHECK(has_feedback_vector());
feedback_vector().ClearOptimizationMarker();
}
bool JSFunction::ChecksOptimizationMarker() {
return code().checks_optimization_marker();
}
bool JSFunction::IsMarkedForOptimization() {
return has_feedback_vector() && feedback_vector().optimization_marker() ==
OptimizationMarker::kCompileOptimized;
}
bool JSFunction::IsMarkedForConcurrentOptimization() {
return has_feedback_vector() &&
feedback_vector().optimization_marker() ==
OptimizationMarker::kCompileOptimizedConcurrent;
}
void JSFunction::MarkForOptimization(ConcurrencyMode mode) {
Isolate* isolate = GetIsolate();
if (!isolate->concurrent_recompilation_enabled() ||
isolate->bootstrapper()->IsActive()) {
mode = ConcurrencyMode::kNotConcurrent;
}
DCHECK(!is_compiled() || ActiveTierIsIgnition() || ActiveTierIsNCI());
DCHECK(!ActiveTierIsTurbofan());
DCHECK(shared().IsInterpreted());
DCHECK(shared().allows_lazy_compilation() ||
!shared().optimization_disabled());
if (mode == ConcurrencyMode::kConcurrent) {
if (IsInOptimizationQueue()) {
if (FLAG_trace_concurrent_recompilation) {
PrintF(" ** Not marking ");
ShortPrint();
PrintF(" -- already in optimization queue.\n");
}
return;
}
if (FLAG_trace_concurrent_recompilation) {
PrintF(" ** Marking ");
ShortPrint();
PrintF(" for concurrent recompilation.\n");
}
}
SetOptimizationMarker(mode == ConcurrencyMode::kConcurrent
? OptimizationMarker::kCompileOptimizedConcurrent
: OptimizationMarker::kCompileOptimized);
}
bool JSFunction::IsInOptimizationQueue() {
return has_feedback_vector() && feedback_vector().optimization_marker() ==
OptimizationMarker::kInOptimizationQueue;
}
void JSFunction::CompleteInobjectSlackTrackingIfActive() {
if (!has_prototype_slot()) return;
if (has_initial_map() && initial_map().IsInobjectSlackTrackingInProgress()) {
initial_map().CompleteInobjectSlackTracking(GetIsolate());
}
}
AbstractCode JSFunction::abstract_code() {
if (ActiveTierIsIgnition()) {
return AbstractCode::cast(shared().GetBytecodeArray());
} else {
return AbstractCode::cast(code());
}
}
int JSFunction::length() { return shared().length(); }
Code JSFunction::code() const {
return Code::cast(RELAXED_READ_FIELD(*this, kCodeOffset));
}
void JSFunction::set_code(Code value) {
DCHECK(!ObjectInYoungGeneration(value));
RELAXED_WRITE_FIELD(*this, kCodeOffset, value);
#ifndef V8_DISABLE_WRITE_BARRIERS
WriteBarrier::Marking(*this, RawField(kCodeOffset), value);
#endif
}
void JSFunction::set_code_no_write_barrier(Code value) {
DCHECK(!ObjectInYoungGeneration(value));
RELAXED_WRITE_FIELD(*this, kCodeOffset, value);
}
// TODO(ishell): Why relaxed read but release store?
DEF_GETTER(JSFunction, shared, SharedFunctionInfo) {
return SharedFunctionInfo::cast(
RELAXED_READ_FIELD(*this, kSharedFunctionInfoOffset));
}
void JSFunction::set_shared(SharedFunctionInfo value, WriteBarrierMode mode) {
// Release semantics to support acquire read in NeedsResetDueToFlushedBytecode
RELEASE_WRITE_FIELD(*this, kSharedFunctionInfoOffset, value);
CONDITIONAL_WRITE_BARRIER(*this, kSharedFunctionInfoOffset, value, mode);
}
void JSFunction::ClearOptimizedCodeSlot(const char* reason) {
if (has_feedback_vector() && feedback_vector().has_optimized_code()) {
if (FLAG_trace_opt) {
CodeTracer::Scope scope(GetIsolate()->GetCodeTracer());
PrintF(scope.file(),
"[evicting entry from optimizing code feedback slot (%s) for ",
reason);
ShortPrint(scope.file());
PrintF(scope.file(), "]\n");
}
feedback_vector().ClearOptimizedCode();
}
}
void JSFunction::SetOptimizationMarker(OptimizationMarker marker) {
DCHECK(has_feedback_vector());
DCHECK(ChecksOptimizationMarker());
DCHECK(!ActiveTierIsTurbofan());
feedback_vector().SetOptimizationMarker(marker);
}
bool JSFunction::has_feedback_vector() const {
return shared().is_compiled() &&
raw_feedback_cell().value().IsFeedbackVector();
}
bool JSFunction::has_closure_feedback_cell_array() const {
return shared().is_compiled() &&
raw_feedback_cell().value().IsClosureFeedbackCellArray();
}
Context JSFunction::context() {
return TaggedField<Context, kContextOffset>::load(*this);
}
bool JSFunction::has_context() const {
return TaggedField<HeapObject, kContextOffset>::load(*this).IsContext();
}
JSGlobalProxy JSFunction::global_proxy() { return context().global_proxy(); }
NativeContext JSFunction::native_context() {
return context().native_context();
}
void JSFunction::set_context(HeapObject value) {
DCHECK(value.IsUndefined() || value.IsContext());
WRITE_FIELD(*this, kContextOffset, value);
WRITE_BARRIER(*this, kContextOffset, value);
}
ACCESSORS_CHECKED(JSFunction, prototype_or_initial_map, HeapObject,
kPrototypeOrInitialMapOffset, map().has_prototype_slot())
DEF_GETTER(JSFunction, has_prototype_slot, bool) {
return map(isolate).has_prototype_slot();
}
DEF_GETTER(JSFunction, initial_map, Map) {
return Map::cast(prototype_or_initial_map(isolate));
}
DEF_GETTER(JSFunction, has_initial_map, bool) {
DCHECK(has_prototype_slot(isolate));
return prototype_or_initial_map(isolate).IsMap(isolate);
}
DEF_GETTER(JSFunction, has_instance_prototype, bool) {
DCHECK(has_prototype_slot(isolate));
// Can't use ReadOnlyRoots(isolate) as this isolate could be produced by
// i::GetIsolateForPtrCompr(HeapObject).
return has_initial_map(isolate) ||
!prototype_or_initial_map(isolate).IsTheHole(
GetReadOnlyRoots(isolate));
}
DEF_GETTER(JSFunction, has_prototype, bool) {
DCHECK(has_prototype_slot(isolate));
return map(isolate).has_non_instance_prototype() ||
has_instance_prototype(isolate);
}
DEF_GETTER(JSFunction, has_prototype_property, bool) {
return (has_prototype_slot(isolate) && IsConstructor(isolate)) ||
IsGeneratorFunction(shared(isolate).kind());
}
DEF_GETTER(JSFunction, PrototypeRequiresRuntimeLookup, bool) {
return !has_prototype_property(isolate) ||
map(isolate).has_non_instance_prototype();
}
DEF_GETTER(JSFunction, instance_prototype, HeapObject) {
DCHECK(has_instance_prototype(isolate));
if (has_initial_map(isolate)) return initial_map(isolate).prototype(isolate);
// When there is no initial map and the prototype is a JSReceiver, the
// initial map field is used for the prototype field.
return HeapObject::cast(prototype_or_initial_map(isolate));
}
DEF_GETTER(JSFunction, prototype, Object) {
DCHECK(has_prototype(isolate));
// If the function's prototype property has been set to a non-JSReceiver
// value, that value is stored in the constructor field of the map.
if (map(isolate).has_non_instance_prototype()) {
Object prototype = map(isolate).GetConstructor(isolate);
// The map must have a prototype in that field, not a back pointer.
DCHECK(!prototype.IsMap(isolate));
DCHECK(!prototype.IsFunctionTemplateInfo(isolate));
return prototype;
}
return instance_prototype(isolate);
}
bool JSFunction::is_compiled() const {
return code().builtin_index() != Builtins::kCompileLazy &&
shared().is_compiled();
}
bool JSFunction::NeedsResetDueToFlushedBytecode() {
// Do a raw read for shared and code fields here since this function may be
// called on a concurrent thread and the JSFunction might not be fully
// initialized yet.
Object maybe_shared = ACQUIRE_READ_FIELD(*this, kSharedFunctionInfoOffset);
Object maybe_code = RELAXED_READ_FIELD(*this, kCodeOffset);
if (!maybe_shared.IsSharedFunctionInfo() || !maybe_code.IsCode()) {
return false;
}
SharedFunctionInfo shared = SharedFunctionInfo::cast(maybe_shared);
Code code = Code::cast(maybe_code);
return !shared.is_compiled() &&
code.builtin_index() != Builtins::kCompileLazy;
}
void JSFunction::ResetIfBytecodeFlushed(
base::Optional<std::function<void(HeapObject object, ObjectSlot slot,
HeapObject target)>>
gc_notify_updated_slot) {
if (FLAG_flush_bytecode && NeedsResetDueToFlushedBytecode()) {
// Bytecode was flushed and function is now uncompiled, reset JSFunction
// by setting code to CompileLazy and clearing the feedback vector.
set_code(GetIsolate()->builtins()->builtin(i::Builtins::kCompileLazy));
raw_feedback_cell().reset_feedback_vector(gc_notify_updated_slot);
}
}
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_JS_FUNCTION_INL_H_

View File

@ -18,24 +18,6 @@
namespace v8 {
namespace internal {
TQ_OBJECT_CONSTRUCTORS_IMPL_NONINLINE(JSFunctionOrBoundFunction)
TQ_OBJECT_CONSTRUCTORS_IMPL_NONINLINE(JSBoundFunction)
OBJECT_CONSTRUCTORS_IMPL_NONINLINE(JSFunction, JSFunctionOrBoundFunction)
CAST_ACCESSOR(JSFunction)
ACCESSORS(JSFunction, raw_feedback_cell, FeedbackCell, kFeedbackCellOffset)
FeedbackVector JSFunction::feedback_vector() const {
DCHECK(has_feedback_vector());
return FeedbackVector::cast(raw_feedback_cell().value());
}
ClosureFeedbackCellArray JSFunction::closure_feedback_cell_array() const {
DCHECK(has_closure_feedback_cell_array());
return ClosureFeedbackCellArray::cast(raw_feedback_cell().value());
}
CodeKinds JSFunction::GetAttachedCodeKinds() const {
CodeKinds result;
@ -167,230 +149,6 @@ bool JSFunction::CanDiscardCompiled() const {
return (result & kJSFunctionCodeKindsMask) != 0;
}
bool JSFunction::HasOptimizationMarker() {
return has_feedback_vector() && feedback_vector().has_optimization_marker();
}
void JSFunction::ClearOptimizationMarker() {
DCHECK(has_feedback_vector());
feedback_vector().ClearOptimizationMarker();
}
bool JSFunction::ChecksOptimizationMarker() {
return code().checks_optimization_marker();
}
bool JSFunction::IsMarkedForOptimization() {
return has_feedback_vector() && feedback_vector().optimization_marker() ==
OptimizationMarker::kCompileOptimized;
}
bool JSFunction::IsMarkedForConcurrentOptimization() {
return has_feedback_vector() &&
feedback_vector().optimization_marker() ==
OptimizationMarker::kCompileOptimizedConcurrent;
}
bool JSFunction::IsInOptimizationQueue() {
return has_feedback_vector() && feedback_vector().optimization_marker() ==
OptimizationMarker::kInOptimizationQueue;
}
void JSFunction::CompleteInobjectSlackTrackingIfActive() {
if (!has_prototype_slot()) return;
if (has_initial_map() && initial_map().IsInobjectSlackTrackingInProgress()) {
initial_map().CompleteInobjectSlackTracking(GetIsolate());
}
}
AbstractCode JSFunction::abstract_code() {
if (ActiveTierIsIgnition()) {
return AbstractCode::cast(shared().GetBytecodeArray());
} else {
return AbstractCode::cast(code());
}
}
int JSFunction::length() { return shared().length(); }
Code JSFunction::code() const {
return Code::cast(RELAXED_READ_FIELD(*this, kCodeOffset));
}
void JSFunction::set_code(Code value) {
DCHECK(!ObjectInYoungGeneration(value));
RELAXED_WRITE_FIELD(*this, kCodeOffset, value);
#ifndef V8_DISABLE_WRITE_BARRIERS
WriteBarrier::Marking(*this, RawField(kCodeOffset), value);
#endif
}
void JSFunction::set_code_no_write_barrier(Code value) {
DCHECK(!ObjectInYoungGeneration(value));
RELAXED_WRITE_FIELD(*this, kCodeOffset, value);
}
// TODO(ishell): Why relaxed read but release store?
DEF_GETTER(JSFunction, shared, SharedFunctionInfo) {
return SharedFunctionInfo::cast(
RELAXED_READ_FIELD(*this, kSharedFunctionInfoOffset));
}
void JSFunction::set_shared(SharedFunctionInfo value, WriteBarrierMode mode) {
// Release semantics to support acquire read in NeedsResetDueToFlushedBytecode
RELEASE_WRITE_FIELD(*this, kSharedFunctionInfoOffset, value);
CONDITIONAL_WRITE_BARRIER(*this, kSharedFunctionInfoOffset, value, mode);
}
void JSFunction::ClearOptimizedCodeSlot(const char* reason) {
if (has_feedback_vector() && feedback_vector().has_optimized_code()) {
if (FLAG_trace_opt) {
CodeTracer::Scope scope(GetIsolate()->GetCodeTracer());
PrintF(scope.file(),
"[evicting entry from optimizing code feedback slot (%s) for ",
reason);
ShortPrint(scope.file());
PrintF(scope.file(), "]\n");
}
feedback_vector().ClearOptimizedCode();
}
}
void JSFunction::SetOptimizationMarker(OptimizationMarker marker) {
DCHECK(has_feedback_vector());
DCHECK(ChecksOptimizationMarker());
DCHECK(!ActiveTierIsTurbofan());
feedback_vector().SetOptimizationMarker(marker);
}
bool JSFunction::has_feedback_vector() const {
return shared().is_compiled() &&
raw_feedback_cell().value().IsFeedbackVector();
}
bool JSFunction::has_closure_feedback_cell_array() const {
return shared().is_compiled() &&
raw_feedback_cell().value().IsClosureFeedbackCellArray();
}
Context JSFunction::context() {
return TaggedField<Context, kContextOffset>::load(*this);
}
bool JSFunction::has_context() const {
return TaggedField<HeapObject, kContextOffset>::load(*this).IsContext();
}
JSGlobalProxy JSFunction::global_proxy() { return context().global_proxy(); }
NativeContext JSFunction::native_context() {
return context().native_context();
}
void JSFunction::set_context(HeapObject value) {
DCHECK(value.IsUndefined() || value.IsContext());
WRITE_FIELD(*this, kContextOffset, value);
WRITE_BARRIER(*this, kContextOffset, value);
}
ACCESSORS_CHECKED(JSFunction, prototype_or_initial_map, HeapObject,
kPrototypeOrInitialMapOffset, map().has_prototype_slot())
DEF_GETTER(JSFunction, has_prototype_slot, bool) {
return map(isolate).has_prototype_slot();
}
DEF_GETTER(JSFunction, initial_map, Map) {
return Map::cast(prototype_or_initial_map(isolate));
}
DEF_GETTER(JSFunction, has_initial_map, bool) {
DCHECK(has_prototype_slot(isolate));
return prototype_or_initial_map(isolate).IsMap(isolate);
}
DEF_GETTER(JSFunction, has_instance_prototype, bool) {
DCHECK(has_prototype_slot(isolate));
// Can't use ReadOnlyRoots(isolate) as this isolate could be produced by
// i::GetIsolateForPtrCompr(HeapObject).
return has_initial_map(isolate) ||
!prototype_or_initial_map(isolate).IsTheHole(
GetReadOnlyRoots(isolate));
}
DEF_GETTER(JSFunction, has_prototype, bool) {
DCHECK(has_prototype_slot(isolate));
return map(isolate).has_non_instance_prototype() ||
has_instance_prototype(isolate);
}
DEF_GETTER(JSFunction, has_prototype_property, bool) {
return (has_prototype_slot(isolate) && IsConstructor(isolate)) ||
IsGeneratorFunction(shared(isolate).kind());
}
DEF_GETTER(JSFunction, PrototypeRequiresRuntimeLookup, bool) {
return !has_prototype_property(isolate) ||
map(isolate).has_non_instance_prototype();
}
DEF_GETTER(JSFunction, instance_prototype, HeapObject) {
DCHECK(has_instance_prototype(isolate));
if (has_initial_map(isolate)) return initial_map(isolate).prototype(isolate);
// When there is no initial map and the prototype is a JSReceiver, the
// initial map field is used for the prototype field.
return HeapObject::cast(prototype_or_initial_map(isolate));
}
DEF_GETTER(JSFunction, prototype, Object) {
DCHECK(has_prototype(isolate));
// If the function's prototype property has been set to a non-JSReceiver
// value, that value is stored in the constructor field of the map.
if (map(isolate).has_non_instance_prototype()) {
Object prototype = map(isolate).GetConstructor(isolate);
// The map must have a prototype in that field, not a back pointer.
DCHECK(!prototype.IsMap(isolate));
DCHECK(!prototype.IsFunctionTemplateInfo(isolate));
return prototype;
}
return instance_prototype(isolate);
}
bool JSFunction::is_compiled() const {
return code().builtin_index() != Builtins::kCompileLazy &&
shared().is_compiled();
}
bool JSFunction::NeedsResetDueToFlushedBytecode() {
// Do a raw read for shared and code fields here since this function may be
// called on a concurrent thread and the JSFunction might not be fully
// initialized yet.
Object maybe_shared = ACQUIRE_READ_FIELD(*this, kSharedFunctionInfoOffset);
Object maybe_code = RELAXED_READ_FIELD(*this, kCodeOffset);
if (!maybe_shared.IsSharedFunctionInfo() || !maybe_code.IsCode()) {
return false;
}
SharedFunctionInfo shared = SharedFunctionInfo::cast(maybe_shared);
Code code = Code::cast(maybe_code);
return !shared.is_compiled() &&
code.builtin_index() != Builtins::kCompileLazy;
}
void JSFunction::ResetIfBytecodeFlushed(
base::Optional<std::function<void(HeapObject object, ObjectSlot slot,
HeapObject target)>>
gc_notify_updated_slot) {
if (FLAG_flush_bytecode && NeedsResetDueToFlushedBytecode()) {
// Bytecode was flushed and function is now uncompiled, reset JSFunction
// by setting code to CompileLazy and clearing the feedback vector.
set_code(GetIsolate()->builtins()->builtin(i::Builtins::kCompileLazy));
raw_feedback_cell().reset_feedback_vector(gc_notify_updated_slot);
}
}
// static
MaybeHandle<NativeContext> JSBoundFunction::GetFunctionRealm(
Handle<JSBoundFunction> function) {
@ -473,40 +231,6 @@ Handle<NativeContext> JSFunction::GetFunctionRealm(
return handle(function->context().native_context(), function->GetIsolate());
}
void JSFunction::MarkForOptimization(ConcurrencyMode mode) {
Isolate* isolate = GetIsolate();
if (!isolate->concurrent_recompilation_enabled() ||
isolate->bootstrapper()->IsActive()) {
mode = ConcurrencyMode::kNotConcurrent;
}
DCHECK(!is_compiled() || ActiveTierIsIgnition() || ActiveTierIsNCI());
DCHECK(!ActiveTierIsTurbofan());
DCHECK(shared().IsInterpreted());
DCHECK(shared().allows_lazy_compilation() ||
!shared().optimization_disabled());
if (mode == ConcurrencyMode::kConcurrent) {
if (IsInOptimizationQueue()) {
if (FLAG_trace_concurrent_recompilation) {
PrintF(" ** Not marking ");
ShortPrint();
PrintF(" -- already in optimization queue.\n");
}
return;
}
if (FLAG_trace_concurrent_recompilation) {
PrintF(" ** Marking ");
ShortPrint();
PrintF(" for concurrent recompilation.\n");
}
}
SetOptimizationMarker(mode == ConcurrencyMode::kConcurrent
? OptimizationMarker::kCompileOptimizedConcurrent
: OptimizationMarker::kCompileOptimized);
}
// static
void JSFunction::EnsureClosureFeedbackCellArray(Handle<JSFunction> function) {
Isolate* const isolate = function->GetIsolate();

View File

@ -24,7 +24,7 @@ class JSFunctionOrBoundFunction
JSObject> {
public:
STATIC_ASSERT(kHeaderSize == JSObject::kHeaderSize);
TQ_OBJECT_CONSTRUCTORS_NONINLINE(JSFunctionOrBoundFunction)
TQ_OBJECT_CONSTRUCTORS(JSFunctionOrBoundFunction)
};
// JSBoundFunction describes a bound function exotic object.
@ -47,18 +47,18 @@ class JSBoundFunction
// to ES6 section 19.2.3.5 Function.prototype.toString ( ).
static Handle<String> ToString(Handle<JSBoundFunction> function);
TQ_OBJECT_CONSTRUCTORS_NONINLINE(JSBoundFunction)
TQ_OBJECT_CONSTRUCTORS(JSBoundFunction)
};
// JSFunction describes JavaScript functions.
class JSFunction : public JSFunctionOrBoundFunction {
public:
// [prototype_or_initial_map]:
DECL_ACCESSORS_NONINLINE(prototype_or_initial_map, HeapObject)
DECL_ACCESSORS(prototype_or_initial_map, HeapObject)
// [shared]: The information about the function that
// can be shared by instances.
DECL_ACCESSORS_NONINLINE(shared, SharedFunctionInfo)
DECL_ACCESSORS(shared, SharedFunctionInfo)
static const int kLengthDescriptorIndex = 0;
static const int kNameDescriptorIndex = 1;
@ -68,12 +68,12 @@ class JSFunction : public JSFunctionOrBoundFunction {
static const int kMinDescriptorsForFastBind = 2;
// [context]: The context for this function.
V8_EXPORT_PRIVATE Context context();
bool has_context() const;
void set_context(HeapObject context);
JSGlobalProxy global_proxy();
V8_EXPORT_PRIVATE NativeContext native_context();
int length();
inline Context context();
inline bool has_context() const;
inline void set_context(HeapObject context);
inline JSGlobalProxy global_proxy();
inline NativeContext native_context();
inline int length();
static Handle<Object> GetName(Isolate* isolate, Handle<JSFunction> function);
static Handle<NativeContext> GetFunctionRealm(Handle<JSFunction> function);
@ -82,13 +82,13 @@ class JSFunction : public JSFunctionOrBoundFunction {
// when the function is invoked, e.g. foo() or new foo(). See
// [[Call]] and [[Construct]] description in ECMA-262, section
// 8.6.2, page 27.
V8_EXPORT_PRIVATE Code code() const;
V8_EXPORT_PRIVATE void set_code(Code code);
void set_code_no_write_barrier(Code code);
inline Code code() const;
inline void set_code(Code code);
inline void set_code_no_write_barrier(Code code);
// Get the abstract code associated with the function, which will either be
// a Code object or a BytecodeArray.
V8_EXPORT_PRIVATE AbstractCode abstract_code();
inline AbstractCode abstract_code();
// The predicates for querying code kinds related to this function have
// specific terminology:
@ -125,30 +125,30 @@ class JSFunction : public JSFunctionOrBoundFunction {
// Tells whether or not this function checks its optimization marker in its
// feedback vector.
bool ChecksOptimizationMarker();
inline bool ChecksOptimizationMarker();
// Tells whether or not this function has a (non-zero) optimization marker.
bool HasOptimizationMarker();
inline bool HasOptimizationMarker();
// Mark this function for lazy recompilation. The function will be recompiled
// the next time it is executed.
void MarkForOptimization(ConcurrencyMode mode);
inline void MarkForOptimization(ConcurrencyMode mode);
// Tells whether or not the function is already marked for lazy recompilation.
bool IsMarkedForOptimization();
bool IsMarkedForConcurrentOptimization();
inline bool IsMarkedForOptimization();
inline bool IsMarkedForConcurrentOptimization();
// Tells whether or not the function is on the concurrent recompilation queue.
bool IsInOptimizationQueue();
inline bool IsInOptimizationQueue();
// Clears the optimized code slot in the function's feedback vector.
void ClearOptimizedCodeSlot(const char* reason);
inline void ClearOptimizedCodeSlot(const char* reason);
// Sets the optimization marker in the function's feedback vector.
void SetOptimizationMarker(OptimizationMarker marker);
inline void SetOptimizationMarker(OptimizationMarker marker);
// Clears the optimization marker in the function's feedback vector.
void ClearOptimizationMarker();
inline void ClearOptimizationMarker();
// If slack tracking is active, it computes instance size of the initial map
// with minimum permissible object slack. If it is not active, it simply
@ -156,28 +156,28 @@ class JSFunction : public JSFunctionOrBoundFunction {
int ComputeInstanceSizeWithMinSlack(Isolate* isolate);
// Completes inobject slack tracking on initial map if it is active.
void CompleteInobjectSlackTrackingIfActive();
inline void CompleteInobjectSlackTrackingIfActive();
// [raw_feedback_cell]: Gives raw access to the FeedbackCell used to hold the
/// FeedbackVector eventually. Generally this shouldn't be used to get the
// feedback_vector, instead use feedback_vector() which correctly deals with
// the JSFunction's bytecode being flushed.
DECL_ACCESSORS_NONINLINE(raw_feedback_cell, FeedbackCell)
DECL_ACCESSORS(raw_feedback_cell, FeedbackCell)
// Functions related to feedback vector. feedback_vector() can be used once
// the function has feedback vectors allocated. feedback vectors may not be
// available after compile when lazily allocating feedback vectors.
V8_EXPORT_PRIVATE FeedbackVector feedback_vector() const;
V8_EXPORT_PRIVATE bool has_feedback_vector() const;
inline FeedbackVector feedback_vector() const;
inline bool has_feedback_vector() const;
V8_EXPORT_PRIVATE static void EnsureFeedbackVector(
Handle<JSFunction> function, IsCompiledScope* compiled_scope);
// Functions related to clousre feedback cell array that holds feedback cells
// Functions related to closure feedback cell array that holds feedback cells
// used to create closures from this function. We allocate closure feedback
// cell arrays after compile, when we want to allocate feedback vectors
// lazily.
V8_EXPORT_PRIVATE bool has_closure_feedback_cell_array() const;
ClosureFeedbackCellArray closure_feedback_cell_array() const;
inline bool has_closure_feedback_cell_array() const;
inline ClosureFeedbackCellArray closure_feedback_cell_array() const;
static void EnsureClosureFeedbackCellArray(Handle<JSFunction> function);
// Initializes the feedback cell of |function|. In lite mode, this would be
@ -191,20 +191,20 @@ class JSFunction : public JSFunctionOrBoundFunction {
void ClearTypeFeedbackInfo();
// Resets function to clear compiled data after bytecode has been flushed.
bool NeedsResetDueToFlushedBytecode();
void ResetIfBytecodeFlushed(
inline bool NeedsResetDueToFlushedBytecode();
inline void ResetIfBytecodeFlushed(
base::Optional<std::function<void(HeapObject object, ObjectSlot slot,
HeapObject target)>>
gc_notify_updated_slot = base::nullopt);
DECL_GETTER_NONINLINE(has_prototype_slot, bool)
DECL_GETTER(has_prototype_slot, bool)
// The initial map for an object created by this constructor.
DECL_GETTER_NONINLINE(initial_map, Map)
DECL_GETTER(initial_map, Map)
static void SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
Handle<HeapObject> prototype);
DECL_GETTER_NONINLINE(has_initial_map, bool)
DECL_GETTER(has_initial_map, bool)
V8_EXPORT_PRIVATE static void EnsureHasInitialMap(
Handle<JSFunction> function);
@ -219,16 +219,16 @@ class JSFunction : public JSFunctionOrBoundFunction {
// function has an initial map the prototype is set on the initial
// map. Otherwise, the prototype is put in the initial map field
// until an initial map is needed.
DECL_GETTER_NONINLINE(has_prototype, bool)
DECL_GETTER_NONINLINE(has_instance_prototype, bool)
DECL_GETTER_NONINLINE(prototype, Object)
DECL_GETTER_NONINLINE(instance_prototype, HeapObject)
DECL_GETTER_NONINLINE(has_prototype_property, bool)
DECL_GETTER_NONINLINE(PrototypeRequiresRuntimeLookup, bool)
DECL_GETTER(has_prototype, bool)
DECL_GETTER(has_instance_prototype, bool)
DECL_GETTER(prototype, Object)
DECL_GETTER(instance_prototype, HeapObject)
DECL_GETTER(has_prototype_property, bool)
DECL_GETTER(PrototypeRequiresRuntimeLookup, bool)
static void SetPrototype(Handle<JSFunction> function, Handle<Object> value);
// Returns if this function has been compiled to native code yet.
V8_EXPORT_PRIVATE bool is_compiled() const;
inline bool is_compiled() const;
static int GetHeaderSize(bool function_has_prototype_slot) {
return function_has_prototype_slot ? JSFunction::kSizeWithPrototype
@ -238,7 +238,7 @@ class JSFunction : public JSFunctionOrBoundFunction {
// Prints the name of the function using PrintF.
void PrintName(FILE* out = stdout);
DECL_CAST_NONINLINE(JSFunction)
DECL_CAST(JSFunction)
// Calculate the instance size and in-object properties count.
// {CalculateExpectedNofProperties} can trigger compilation.
@ -311,7 +311,7 @@ class JSFunction : public JSFunctionOrBoundFunction {
static constexpr int kSizeWithoutPrototype = kPrototypeOrInitialMapOffset;
static constexpr int kSizeWithPrototype = FieldOffsets::kHeaderSize;
OBJECT_CONSTRUCTORS_NONINLINE(JSFunction, JSFunctionOrBoundFunction);
OBJECT_CONSTRUCTORS(JSFunction, JSFunctionOrBoundFunction);
};
} // namespace internal

View File

@ -11,6 +11,7 @@
#include "src/objects/descriptor-array-inl.h"
#include "src/objects/field-type.h"
#include "src/objects/instance-type-inl.h"
#include "src/objects/js-function-inl.h"
#include "src/objects/layout-descriptor-inl.h"
#include "src/objects/map.h"
#include "src/objects/objects-inl.h"

View File

@ -81,10 +81,3 @@
#undef DEFINE_DEOPT_ENTRY_ACCESSORS
#undef TQ_OBJECT_CONSTRUCTORS
#undef TQ_OBJECT_CONSTRUCTORS_IMPL
#undef OBJECT_CONSTRUCTORS_NONINLINE
#undef OBJECT_CONSTRUCTORS_IMPL_NONINLINE
#undef DECL_GETTER_NONINLINE
#undef DECL_ACCESSORS_NONINLINE
#undef DECL_CAST_NONINLINE
#undef TQ_OBJECT_CONSTRUCTORS_NONINLINE
#undef TQ_OBJECT_CONSTRUCTORS_IMPL_NONINLINE

View File

@ -16,19 +16,6 @@
#include "src/base/memory.h"
// TODO(v8:10749): When we've had a chance to collect performance impact,
// either move towards using _NONINLINE versions everywhere, or revert back to
// inline use and remove _NONINLINE macros.
#define OBJECT_CONSTRUCTORS_NONINLINE(Type, ...) \
public: \
constexpr Type() : __VA_ARGS__() {} \
\
protected: \
template <typename TFieldType, int kFieldOffset> \
friend class TaggedField; \
\
V8_EXPORT_PRIVATE explicit Type(Address ptr)
// Since this changes visibility, it should always be last in a class
// definition.
#define OBJECT_CONSTRUCTORS(Type, ...) \
@ -41,9 +28,6 @@
\
explicit inline Type(Address ptr)
#define OBJECT_CONSTRUCTORS_IMPL_NONINLINE(Type, Super) \
Type::Type(Address ptr) : Super(ptr) { SLOW_DCHECK(Is##Type()); }
#define OBJECT_CONSTRUCTORS_IMPL(Type, Super) \
inline Type::Type(Address ptr) : Super(ptr) { SLOW_DCHECK(Is##Type()); }
// In these cases, we don't have our own instance type to check, so check the
@ -100,10 +84,6 @@
inline type name() const; \
inline type name(const Isolate* isolate) const;
#define DECL_GETTER_NONINLINE(name, type) \
V8_EXPORT_PRIVATE type name() const; \
V8_EXPORT_PRIVATE type name(const Isolate* isolate) const;
#define DEF_GETTER(holder, name, type) \
type holder::name() const { \
const Isolate* isolate = GetIsolateForPtrCompr(*this); \
@ -116,23 +96,12 @@
inline void set_##name(type value, \
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
#define DECL_ACCESSORS_NONINLINE(name, type) \
DECL_GETTER_NONINLINE(name, type) \
V8_EXPORT_PRIVATE void set_##name( \
type value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
// TODO(solanes, neis): Unify naming for synchronized accessor uses.
#define DECL_SYNCHRONIZED_ACCESSORS(name, type) \
DECL_GETTER(synchronized_##name, type) \
inline void set_synchronized_##name( \
type value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
#define DECL_CAST_NONINLINE(Type) \
V8_EXPORT_PRIVATE static Type cast(Object object); \
inline static Type unchecked_cast(Object object) { \
return bit_cast<Type>(object); \
}
#define DECL_CAST(Type) \
V8_INLINE static Type cast(Object object); \
V8_INLINE static Type unchecked_cast(Object object) { \
@ -519,20 +488,6 @@
set(IndexForEntry(i) + k##name##Offset, value); \
}
#define TQ_OBJECT_CONSTRUCTORS_NONINLINE(Type) \
public: \
constexpr Type() = default; \
\
protected: \
template <typename TFieldType, int kFieldOffset> \
friend class TaggedField; \
\
V8_EXPORT_PRIVATE explicit Type(Address ptr); \
friend class TorqueGenerated##Type<Type, Super>;
#define TQ_OBJECT_CONSTRUCTORS_IMPL_NONINLINE(Type) \
Type::Type(Address ptr) : TorqueGenerated##Type<Type, Type::Super>(ptr) {}
#define TQ_OBJECT_CONSTRUCTORS(Type) \
public: \
constexpr Type() = default; \

View File

@ -26,6 +26,7 @@
#include "src/logging/counters.h"
#include "src/objects/heap-object-inl.h"
#include "src/objects/js-array-inl.h"
#include "src/objects/js-function-inl.h"
#include "src/objects/js-regexp-inl.h"
#include "src/objects/smi.h"
#include "src/snapshot/snapshot.h"

View File

@ -13,6 +13,7 @@
#include "src/objects/foreign-inl.h"
#include "src/objects/heap-number-inl.h"
#include "src/objects/js-array-buffer-inl.h"
#include "src/objects/js-function-inl.h"
#include "src/objects/js-objects-inl.h"
#include "src/objects/managed.h"
#include "src/objects/oddball-inl.h"