Commit f8be16a0 authored by Maya Lekova's avatar Maya Lekova Committed by Commit Bot

[gcmole] Relax gcmole reasoning about raw pointers

This CL ensures we care only about our internal pointer types and not
about raw C++ pointers, because normally special care is taken when
storing raw pointers to the managed heap. Furthermore, checking for raw
pointers produces too many false positives in the dead variable
analysis.

Bug: v8:9680, chromium:1000635
Change-Id: Ica9ea1fe09b7456c011910a6886149b6dfdda1f5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1924357
Commit-Queue: Maya Lekova <mslekova@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65174}
parent 3ce6be02
DESCRIPTION -------------------------------------------------------------------
gcmole is a simple static analysis tool used to find possible evaluation order
dependent GC-unsafe places in the V8 codebase.
dependent GC-unsafe places in the V8 codebase and "stale" pointers to the heap
(ones whose addresses got invalidated by the GC).
For example the following code is GC-unsafe:
Handle<Object> Foo(); // Assume Foo can trigger a GC.
void Bar(Object*, Object*);
void Bar(Object, Object);
Handle<Object> baz;
baz->Qux(*Foo()); // (a)
......@@ -17,6 +18,21 @@ includes receiver) in any order. That means it can dereference baz before
calling to Foo and save a raw pointer to a heap object in the register or
on the stack.
In terms of the AST analysis that gcmole does, it warns about places in the
code which result in 2 subtrees, the order of execution of which is undefined
by C++, one of which causes a GC and the other dereferences a Handle to a raw
Object (or its subclasses).
The following code triggers a stale variable warning (assuming that the Foo
function was detected as potentially allocating, as in the previous example):
JSObject raw_obj = ...;
Foo();
raw_obj.Print();
Since Foo can trigger a GC, it might have moved the raw_obj. The solution is
simply to store it as a Handle.
PREREQUISITES -----------------------------------------------------------------
(1) Install Lua 5.1
......
......@@ -130,5 +130,36 @@ void TestFollowingVirtualFunctions(Isolate* isolate) {
so_handle->Method(*base->VirtualCauseGC(obj1, isolate));
}
// --------- Test for correctly resolving static methods ----------
class SomeClass {
public:
static Handle<Object> StaticCauseGC(Handle<Object> obj, Isolate* isolate) {
isolate->heap()->CollectGarbage(OLD_SPACE,
GarbageCollectionReason::kTesting);
return obj;
}
};
void TestFollowingStaticFunctions(Isolate* isolate) {
SomeObject so;
Handle<SomeObject> so_handle = handle(so, isolate);
Handle<JSObject> obj1 = isolate->factory()->NewJSObjectWithNullProto();
// Should cause warning.
so_handle->Method(*SomeClass::StaticCauseGC(obj1, isolate));
}
// --------- Test basic dead variable analysis ----------
void TestDeadVarAnalysis(Isolate* isolate) {
JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
CauseGCRaw(raw_obj, isolate);
// Should cause warning.
raw_obj.Print();
}
} // namespace internal
} // namespace v8
This diff is collapsed.
......@@ -44,6 +44,9 @@ local FLAGS = {
-- TODO add some sort of whiteliste to filter out false positives.
dead_vars = false;
-- Enable verbose tracing from the plugin itself.
verbose_trace = false;
-- When building gcsuspects whitelist certain functions as if they
-- can be causing GC. Currently used to reduce number of false
-- positives in dead variables analysis. See TODO for WHITELIST
......@@ -310,7 +313,10 @@ local WHITELIST = {
"StateTag",
-- Ignore printing of elements transition.
"PrintElementsTransition"
"PrintElementsTransition",
-- CodeCreateEvent receives AbstractCode (a raw ptr) as an argument.
"CodeCreateEvent",
};
local function AddCause(name, cause)
......@@ -443,8 +449,9 @@ local function CheckCorrectnessForArch(arch, for_test)
log("** Searching for evaluation order problems%s for %s",
FLAGS.dead_vars and " and dead variables" or "",
arch)
local plugin_args
if FLAGS.dead_vars then plugin_args = { "--dead-vars" } end
local plugin_args = {}
if FLAGS.dead_vars then table.insert(plugin_args, "--dead-vars") end
if FLAGS.verbose_trace then table.insert(plugin_args, '--verbose') end
InvokeClangPluginForEachFile(files,
cfg:extend { plugin = "find-problems",
plugin_args = plugin_args },
......
......@@ -17,4 +17,7 @@ tools/gcmole/gcmole-test.cc:128:14: warning: Possible problem with evaluation or
tools/gcmole/gcmole-test.cc:130:14: warning: Possible problem with evaluation order.
so_handle->Method(*base->VirtualCauseGC(obj1, isolate));
^
6 warnings generated.
tools/gcmole/gcmole-test.cc:151:14: warning: Possible problem with evaluation order.
so_handle->Method(*SomeClass::StaticCauseGC(obj1, isolate));
^
7 warnings generated.
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