diff options
Diffstat (limited to 'deps/v8/src/objects/js-function-inl.h')
-rw-r--r-- | deps/v8/src/objects/js-function-inl.h | 62 |
1 files changed, 55 insertions, 7 deletions
diff --git a/deps/v8/src/objects/js-function-inl.h b/deps/v8/src/objects/js-function-inl.h index bae63f6ef9..275ffba14d 100644 --- a/deps/v8/src/objects/js-function-inl.h +++ b/deps/v8/src/objects/js-function-inl.h @@ -168,8 +168,12 @@ Address JSFunction::code_entry_point() const { // TODO(ishell): Why relaxed read but release store? DEF_GETTER(JSFunction, shared, SharedFunctionInfo) { - return SharedFunctionInfo::cast( - RELAXED_READ_FIELD(*this, kSharedFunctionInfoOffset)); + return shared(cage_base, kRelaxedLoad); +} + +DEF_RELAXED_GETTER(JSFunction, shared, SharedFunctionInfo) { + return TaggedField<SharedFunctionInfo, + kSharedFunctionInfoOffset>::Relaxed_Load(cage_base, *this); } void JSFunction::set_shared(SharedFunctionInfo value, WriteBarrierMode mode) { @@ -200,6 +204,10 @@ Context JSFunction::context() { return TaggedField<Context, kContextOffset>::load(*this); } +DEF_RELAXED_GETTER(JSFunction, context, Context) { + return TaggedField<Context, kContextOffset>::Relaxed_Load(cage_base, *this); +} + bool JSFunction::has_context() const { return TaggedField<HeapObject, kContextOffset>::load(*this).IsContext(); } @@ -258,8 +266,9 @@ DEF_GETTER(JSFunction, PrototypeRequiresRuntimeLookup, bool) { DEF_GETTER(JSFunction, instance_prototype, HeapObject) { DCHECK(has_instance_prototype(cage_base)); - if (has_initial_map(cage_base)) + if (has_initial_map(cage_base)) { return initial_map(cage_base).prototype(cage_base); + } // 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(cage_base, kAcquireLoad)); @@ -284,14 +293,37 @@ bool JSFunction::is_compiled() const { shared().is_compiled(); } +bool JSFunction::ShouldFlushBaselineCode( + base::EnumSet<CodeFlushMode> code_flush_mode) { + if (!IsBaselineCodeFlushingEnabled(code_flush_mode)) return false; + // Do a raw read for shared and code fields here since this function may be + // called on a concurrent thread. JSFunction itself should be fully + // initialized here but the SharedFunctionInfo, Code objects may not be + // initialized. We read using acquire loads to defend against that. + Object maybe_shared = ACQUIRE_READ_FIELD(*this, kSharedFunctionInfoOffset); + if (!maybe_shared.IsSharedFunctionInfo()) return false; + + // See crbug.com/v8/11972 for more details on acquire / release semantics for + // code field. We don't use release stores when copying code pointers from + // SFI / FV to JSFunction but it is safe in practice. + Object maybe_code = ACQUIRE_READ_FIELD(*this, kCodeOffset); + if (!maybe_code.IsCodeT()) return false; + Code code = FromCodeT(CodeT::cast(maybe_code)); + if (code.kind() != CodeKind::BASELINE) return false; + + SharedFunctionInfo shared = SharedFunctionInfo::cast(maybe_shared); + return shared.ShouldFlushCode(code_flush_mode); +} + 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. + // called on a concurrent thread. JSFunction itself should be fully + // initialized here but the SharedFunctionInfo, Code objects may not be + // initialized. We read using acquire loads to defend against that. Object maybe_shared = ACQUIRE_READ_FIELD(*this, kSharedFunctionInfoOffset); if (!maybe_shared.IsSharedFunctionInfo()) return false; - Object maybe_code = RELAXED_READ_FIELD(*this, kCodeOffset); + Object maybe_code = ACQUIRE_READ_FIELD(*this, kCodeOffset); if (!maybe_code.IsCodeT()) return false; Code code = FromCodeT(CodeT::cast(maybe_code), kRelaxedLoad); @@ -299,15 +331,31 @@ bool JSFunction::NeedsResetDueToFlushedBytecode() { return !shared.is_compiled() && code.builtin_id() != Builtin::kCompileLazy; } -void JSFunction::ResetIfBytecodeFlushed( +bool JSFunction::NeedsResetDueToFlushedBaselineCode() { + return code().kind() == CodeKind::BASELINE && !shared().HasBaselineData(); +} + +void JSFunction::ResetIfCodeFlushed( base::Optional<std::function<void(HeapObject object, ObjectSlot slot, HeapObject target)>> gc_notify_updated_slot) { + if (!FLAG_flush_bytecode && !FLAG_flush_baseline_code) return; + + DCHECK_IMPLIES(NeedsResetDueToFlushedBytecode(), FLAG_flush_bytecode); 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(*BUILTIN_CODE(GetIsolate(), CompileLazy)); raw_feedback_cell().reset_feedback_vector(gc_notify_updated_slot); + return; + } + + DCHECK_IMPLIES(NeedsResetDueToFlushedBaselineCode(), + FLAG_flush_baseline_code); + if (FLAG_flush_baseline_code && NeedsResetDueToFlushedBaselineCode()) { + DCHECK(FLAG_flush_baseline_code); + // Flush baseline code from the closure if required + set_code(*BUILTIN_CODE(GetIsolate(), InterpreterEntryTrampoline)); } } |