Commit 873f66cd authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

api,heap: Add support for on-stack TracedGlobal

Similar to TracedReference, support TracedGlobal on stack as well.

Bug: chromium:1040038
Change-Id: If3400a2df8b4a11410032bd5ad1b7bed64063b93
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2005071
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65841}
parent be03c645
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "src/sanitizer/asan.h" #include "src/sanitizer/asan.h"
#include "src/tasks/cancelable-task.h" #include "src/tasks/cancelable-task.h"
#include "src/tasks/task-utils.h" #include "src/tasks/task-utils.h"
#include "src/utils/utils.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -690,6 +691,12 @@ class GlobalHandles::TracedNode final ...@@ -690,6 +691,12 @@ class GlobalHandles::TracedNode final
DCHECK(!IsInUse()); DCHECK(!IsInUse());
} }
void Verify() {
DCHECK(IsInUse());
DCHECK_IMPLIES(!has_destructor(), nullptr == parameter());
DCHECK_IMPLIES(has_destructor() && !HasFinalizationCallback(), parameter());
}
protected: protected:
using NodeState = base::BitField8<State, 0, 2>; using NodeState = base::BitField8<State, 0, 2>;
using IsInYoungList = NodeState::Next<bool, 1>; using IsInYoungList = NodeState::Next<bool, 1>;
...@@ -762,14 +769,6 @@ class GlobalHandles::OnStackTracedNodeSpace final { ...@@ -762,14 +769,6 @@ class GlobalHandles::OnStackTracedNodeSpace final {
uintptr_t GetStackAddressForSlot(uintptr_t slot) const; uintptr_t GetStackAddressForSlot(uintptr_t slot) const;
V8_NOINLINE uintptr_t GetCurrentStackPosition() const {
#if V8_CC_MSVC
return reinterpret_cast<uintptr_t>(_AddressOfReturnAddress());
#else
return reinterpret_cast<uintptr_t>(__builtin_frame_address(0));
#endif // V8_CC_MSVC
}
// Keeps track of registered handles and their stack address. The data // Keeps track of registered handles and their stack address. The data
// structure is cleaned on iteration and when adding new references using the // structure is cleaned on iteration and when adding new references using the
// current stack address. // current stack address.
...@@ -894,8 +893,6 @@ Handle<Object> GlobalHandles::CreateTraced(Object value, Address* slot, ...@@ -894,8 +893,6 @@ Handle<Object> GlobalHandles::CreateTraced(Object value, Address* slot,
bool is_on_stack) { bool is_on_stack) {
GlobalHandles::TracedNode* result; GlobalHandles::TracedNode* result;
if (is_on_stack) { if (is_on_stack) {
CHECK_WITH_MSG(!has_destructor,
"TracedGlobal is prohibited from on-stack usage.");
result = on_stack_nodes_->Acquire(value, reinterpret_cast<uintptr_t>(slot)); result = on_stack_nodes_->Acquire(value, reinterpret_cast<uintptr_t>(slot));
} else { } else {
result = traced_nodes_->Acquire(value); result = traced_nodes_->Acquire(value);
...@@ -903,9 +900,9 @@ Handle<Object> GlobalHandles::CreateTraced(Object value, Address* slot, ...@@ -903,9 +900,9 @@ Handle<Object> GlobalHandles::CreateTraced(Object value, Address* slot,
traced_young_nodes_.push_back(result); traced_young_nodes_.push_back(result);
result->set_in_young_list(true); result->set_in_young_list(true);
} }
result->set_parameter(slot);
result->set_has_destructor(has_destructor);
} }
result->set_has_destructor(has_destructor);
result->set_parameter(has_destructor ? slot : nullptr);
return result->handle(); return result->handle();
} }
...@@ -934,7 +931,9 @@ void GlobalHandles::CopyTracedGlobal(const Address* const* from, Address** to) { ...@@ -934,7 +931,9 @@ void GlobalHandles::CopyTracedGlobal(const Address* const* from, Address** to) {
// Copying a traced handle with finalization callback is prohibited because // Copying a traced handle with finalization callback is prohibited because
// the callback may require knowing about multiple copies of the traced // the callback may require knowing about multiple copies of the traced
// handle. // handle.
CHECK(!node->HasFinalizationCallback()); CHECK_WITH_MSG(!node->HasFinalizationCallback(),
"Copying of references is not supported when "
"SetFinalizationCallback is set.");
GlobalHandles* global_handles = GlobalHandles* global_handles =
GlobalHandles::From(const_cast<TracedNode*>(node)); GlobalHandles::From(const_cast<TracedNode*>(node));
...@@ -983,35 +982,53 @@ void GlobalHandles::MoveTracedGlobal(Address** from, Address** to) { ...@@ -983,35 +982,53 @@ void GlobalHandles::MoveTracedGlobal(Address** from, Address** to) {
reinterpret_cast<uintptr_t>(to)); reinterpret_cast<uintptr_t>(to));
} }
// Moving a traced handle with finalization callback is prohibited because
// the callback may require knowing about multiple copies of the traced
// handle.
CHECK_WITH_MSG(!from_node->HasFinalizationCallback(),
"Moving of references is not supported when "
"SetFinalizationCallback is set.");
// Types in v8.h ensure that we only copy/move handles that have the same
// destructor behavior.
DCHECK_IMPLIES(to_node,
to_node->has_destructor() == from_node->has_destructor());
// Moving. // Moving.
if (from_on_stack || to_on_stack) { if (from_on_stack || to_on_stack) {
// Move involving a stack slot. // Move involving a stack slot.
DCHECK(!from_node->has_destructor());
DCHECK(!from_node->HasFinalizationCallback());
if (!to_node) { if (!to_node) {
DCHECK(global_handles); DCHECK(global_handles);
Handle<Object> o = global_handles->CreateTraced( Handle<Object> o = global_handles->CreateTraced(
from_node->object(), reinterpret_cast<Address*>(to), false, from_node->object(), reinterpret_cast<Address*>(to),
to_on_stack); from_node->has_destructor(), to_on_stack);
*to = o.location(); *to = o.location();
DCHECK(TracedNode::FromLocation(*to)->markbit()); to_node = TracedNode::FromLocation(*to);
DCHECK(to_node->markbit());
} else { } else {
// To node already exists, just copy fields. // To node already exists, just copy fields.
*TracedNode::FromLocation(*to) = *from_node; *TracedNode::FromLocation(*to) = *from_node;
// Fixup back reference for destructor.
if (to_node->has_destructor()) {
to_node->set_parameter(to);
}
} }
DestroyTraced(*from); DestroyTraced(*from);
*from = nullptr; *from = nullptr;
to_node->Verify();
} else { } else {
// Pure heap move. // Pure heap move.
DestroyTraced(*to); DestroyTraced(*to);
*to = *from; *to = *from;
to_node = from_node;
DCHECK_NOT_NULL(*from); DCHECK_NOT_NULL(*from);
DCHECK_NOT_NULL(*to); DCHECK_NOT_NULL(*to);
DCHECK_EQ(*from, *to); DCHECK_EQ(*from, *to);
if (!from_node->HasFinalizationCallback()) { // Fixup back reference for destructor.
from_node->set_parameter(to); if (to_node->has_destructor()) {
to_node->set_parameter(to);
} }
*from = nullptr; *from = nullptr;
to_node->Verify();
} }
} }
......
This diff is collapsed.
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