summaryrefslogtreecommitdiff
path: root/deps/v8/src/objects/js-function-inl.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/objects/js-function-inl.h')
-rw-r--r--deps/v8/src/objects/js-function-inl.h62
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));
}
}