Remove almost all of Oilpan

The only things left are all the baseclasses
and macros in heap/Handle.h which are referenced
throughout all of core.

R=abarth@chromium.org

Review URL: https://codereview.chromium.org/686783002
This commit is contained in:
Eric Seidel 2014-10-28 09:36:50 -07:00
parent 42ea48b379
commit c32433111b
36 changed files with 23 additions and 2896 deletions

View File

@ -32,6 +32,7 @@
#define DOMWrapperWorld_h
#include "bindings/core/v8/ScriptState.h"
#include "wtf/HashSet.h"
#include "wtf/MainThread.h"
#include "wtf/PassRefPtr.h"
#include "wtf/RefCounted.h"
@ -141,7 +142,7 @@ private:
{
}
Persistent<T> m_object;
OwnPtr<T> m_object;
};
public:

View File

@ -1,28 +0,0 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "config.h"
#include "bindings/core/v8/ScriptFunction.h"
#include "bindings/core/v8/V8Binding.h"
namespace blink {
v8::Handle<v8::Function> ScriptFunction::bindToV8Function()
{
v8::Isolate* isolate = m_scriptState->isolate();
v8::Handle<v8::External> wrapper = v8::External::New(isolate, this);
m_scriptState->world().registerDOMObjectHolder(isolate, this, wrapper);
return createClosure(&ScriptFunction::callCallback, wrapper, isolate);
}
void ScriptFunction::callCallback(const v8::FunctionCallbackInfo<v8::Value>& args)
{
ASSERT(args.Data()->IsExternal());
ScriptFunction* scriptFunction = static_cast<ScriptFunction*>(v8::Handle<v8::External>::Cast(args.Data())->Value());
ScriptValue result = scriptFunction->call(ScriptValue(scriptFunction->scriptState(), args[0]));
v8SetReturnValue(args, result.v8Value());
}
} // namespace blink

View File

@ -1,74 +0,0 @@
/*
* Copyright (C) 2013 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef ScriptFunction_h
#define ScriptFunction_h
#include "bindings/core/v8/ScriptValue.h"
#include "platform/heap/Handle.h"
#include <v8.h>
namespace blink {
// A common way of using ScriptFunction is as follows:
//
// class DerivedFunction : public ScriptFunction {
// // This returns a V8 function which the DerivedFunction is bound to.
// // The DerivedFunction is destructed when the V8 function is
// // garbage-collected.
// static v8::Handle<v8::Function> createFunction(ScriptState* scriptState)
// {
// DerivedFunction* self = new DerivedFunction(scriptState);
// return self->bindToV8Function();
// }
// };
class ScriptFunction {
public:
virtual ~ScriptFunction() { }
ScriptState* scriptState() const { return m_scriptState.get(); }
protected:
explicit ScriptFunction(ScriptState* scriptState)
: m_scriptState(scriptState)
{
}
v8::Handle<v8::Function> bindToV8Function();
private:
virtual ScriptValue call(ScriptValue) = 0;
static void callCallback(const v8::FunctionCallbackInfo<v8::Value>&);
RefPtr<ScriptState> m_scriptState;
};
} // namespace blink
#endif

View File

@ -31,7 +31,6 @@
#ifndef ScriptPromise_h
#define ScriptPromise_h
#include "bindings/core/v8/ScriptFunction.h"
#include "bindings/core/v8/ScriptValue.h"
#include "bindings/core/v8/V8ThrowException.h"
#include "core/dom/ExceptionCode.h"

View File

@ -49,8 +49,6 @@
'ScriptCallStackFactory.h',
'ScriptController.cpp',
'ScriptController.h',
'ScriptFunction.cpp',
'ScriptFunction.h',
'ScriptFunctionCall.cpp',
'ScriptFunctionCall.h',
'ScriptGCEvent.cpp',

View File

@ -45,14 +45,7 @@ CSSImageGeneratorValue::~CSSImageGeneratorValue()
void CSSImageGeneratorValue::addClient(RenderObject* renderer, const IntSize& size)
{
ASSERT(renderer);
#if !ENABLE(OILPAN)
ref();
#else
if (m_clients.isEmpty()) {
ASSERT(!m_keepAlive);
m_keepAlive = adoptPtr(new Persistent<CSSImageGeneratorValue>(this));
}
#endif
if (!size.isEmpty())
m_sizes.add(size);

View File

@ -241,12 +241,6 @@ inline bool compareCSSValuePtr(const RawPtr<CSSValueType>& first, const RawPtr<C
return first ? second && first->equals(*second) : !second;
}
template<typename CSSValueType>
inline bool compareCSSValuePtr(const Member<CSSValueType>& first, const Member<CSSValueType>& second)
{
return first ? second && first->equals(*second) : !second;
}
#define DEFINE_CSS_VALUE_TYPE_CASTS(thisType, predicate) \
DEFINE_TYPE_CASTS(thisType, CSSValue, value, value->predicate, value.predicate)

View File

@ -354,7 +354,7 @@ void FontFace::setError(PassRefPtr<DOMException> error)
ScriptPromise FontFace::fontStatusPromise(ScriptState* scriptState)
{
if (!m_loadedProperty) {
m_loadedProperty = new LoadedProperty(scriptState->executionContext(), this, LoadedProperty::Loaded);
m_loadedProperty = adoptPtr(new LoadedProperty(scriptState->executionContext(), this, LoadedProperty::Loaded));
if (m_status == Loaded)
m_loadedProperty->resolve(this);
else if (m_status == Error)

View File

@ -130,7 +130,7 @@ private:
LoadStatus m_status;
RefPtr<DOMException> m_error;
Persistent<LoadedProperty> m_loadedProperty;
OwnPtr<LoadedProperty> m_loadedProperty;
OwnPtr<CSSFontFace> m_cssFontFace;
Vector<RefPtr<LoadFontCallback> > m_callbacks;
};

View File

@ -248,16 +248,6 @@ inline MutableStylePropertySet* toMutableStylePropertySet(const RefPtr<StyleProp
return toMutableStylePropertySet(set.get());
}
inline MutableStylePropertySet* toMutableStylePropertySet(const Persistent<StylePropertySet>& set)
{
return toMutableStylePropertySet(set.get());
}
inline MutableStylePropertySet* toMutableStylePropertySet(const Member<StylePropertySet>& set)
{
return toMutableStylePropertySet(set.get());
}
inline const StylePropertyMetadata& StylePropertySet::PropertyReference::propertyMetadata() const
{
if (m_propertySet.isMutable())

View File

@ -12,6 +12,7 @@ namespace blink {
class DescendantInvalidationSet;
class Document;
class Element;
class Node;
class StyleInvalidator {
DISALLOW_ALLOCATION();

View File

@ -33,11 +33,7 @@ class MediaQueryResult : public RefCounted<MediaQueryResult> {
WTF_MAKE_NONCOPYABLE(MediaQueryResult); WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED;
public:
MediaQueryResult(const MediaQueryExp& expr, bool result)
#if ENABLE(OILPAN)
: m_expression(&expr)
#else
: m_expression(expr)
#endif
, m_result(result)
{
}
@ -46,21 +42,13 @@ public:
const MediaQueryExp* expression() const
{
#if ENABLE(OILPAN)
return m_expression;
#else
return &m_expression;
#endif
}
bool result() const { return m_result; }
private:
#if ENABLE(OILPAN)
Member<const MediaQueryExp> m_expression;
#else
MediaQueryExp m_expression;
#endif
bool m_result;
};

View File

@ -3141,10 +3141,6 @@ bool Document::hasFocus() const
return focusedFrame && focusedFrame == frame();
}
void Document::clearWeakMembers(Visitor* visitor)
{
}
v8::Handle<v8::Object> Document::wrap(v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
{
ASSERT(!DOMDataStore::containsWrapperNonTemplate(this, isolate));

View File

@ -694,8 +694,6 @@ private:
void detachParser();
void clearWeakMembers(Visitor*);
virtual bool isDocument() const override final { return true; }
virtual void childrenChanged(const ChildrenChange&) override;

View File

@ -195,31 +195,6 @@ void EventHandlerRegistry::notifyDidAddOrRemoveEventHandlerTarget(EventHandlerCl
scrollingCoordinator->touchEventTargetRectsDidChange();
}
void EventHandlerRegistry::trace(Visitor* visitor)
{
visitor->registerWeakMembers<EventHandlerRegistry, &EventHandlerRegistry::clearWeakMembers>(this);
}
void EventHandlerRegistry::clearWeakMembers(Visitor* visitor)
{
Vector<EventTarget*> deadTargets;
for (size_t i = 0; i < EventHandlerClassCount; ++i) {
EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
const EventTargetSet* targets = &m_targets[handlerClass];
for (EventTargetSet::const_iterator it = targets->begin(); it != targets->end(); ++it) {
Node* node = it->key->toNode();
LocalDOMWindow* window = it->key->toDOMWindow();
if (node && !visitor->isAlive(node)) {
deadTargets.append(node);
} else if (window && !visitor->isAlive(window)) {
deadTargets.append(window);
}
}
}
for (size_t i = 0; i < deadTargets.size(); ++i)
didRemoveAllEventHandlers(*deadTargets[i]);
}
void EventHandlerRegistry::documentDetached(Document& document)
{
// Remove all event targets under the detached document.

View File

@ -59,9 +59,6 @@ public:
// references to handlers that are no longer related to it.
void documentDetached(Document&);
void trace(Visitor*);
void clearWeakMembers(Visitor*);
private:
enum ChangeOperation {
Add, // Add a new event handler.

View File

@ -35,6 +35,7 @@
#include "platform/graphics/Color.h"
#include "platform/scroll/ScrollableArea.h"
#include "wtf/Forward.h"
#include "wtf/HashSet.h"
#include "wtf/OwnPtr.h"
#include "wtf/text/WTFString.h"

View File

@ -7,6 +7,7 @@
#include "core/inspector/ConsoleMessage.h"
#include "platform/heap/Handle.h"
#include "wtf/Deque.h"
#include "wtf/Forward.h"
namespace blink {

View File

@ -26,18 +26,6 @@ bool dataEquivalent(const RefPtr<T>& a, const RefPtr<T>& b)
return dataEquivalent(a.get(), b.get());
}
template <typename T>
bool dataEquivalent(const Persistent<T>& a, const Persistent<T>& b)
{
return dataEquivalent(a.get(), b.get());
}
template <typename T>
bool dataEquivalent(const Member<T>& a, const Member<T>& b)
{
return dataEquivalent(a.get(), b.get());
}
template <typename T>
bool dataEquivalent(const OwnPtr<T>& a, const OwnPtr<T>& b)
{

View File

@ -26,6 +26,7 @@
#ifndef MediaPlayer_h
#define MediaPlayer_h
#include "platform/PlatformExport.h"
#include "public/platform/WebMediaPlayer.h"
#include "wtf/Forward.h"
#include "wtf/Noncopyable.h"

View File

@ -1,65 +0,0 @@
/*
* Copyright (C) 2014 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef AddressSanitizer_h
#define AddressSanitizer_h
// FIXME: Add SyZyASan support?
#if defined(ADDRESS_SANITIZER)
#include <sanitizer/asan_interface.h>
#else
#define ASAN_POISON_MEMORY_REGION(addr, size) \
((void)(addr), (void)(size))
#define ASAN_UNPOISON_MEMORY_REGION(addr, size) \
((void)(addr), (void)(size))
#endif
#if defined(LEAK_SANITIZER)
#include <sanitizer/lsan_interface.h>
#else
#define __lsan_register_root_region(addr, size) ((void)(addr), (void)(size))
#define __lsan_unregister_root_region(addr, size) ((void)(addr), (void)(size))
#endif
// FIXME: Have to handle (ADDRESS_SANITIZER && _WIN32) differently as it uses
// both Clang (which supports the __attribute__ syntax) and CL (which doesn't)
// as long as we use "clang-cl /fallback". This shouldn't be needed when Clang
// handles all the code without falling back to CL.
#if defined(ADDRESS_SANITIZER) && (!OS(WIN) || COMPILER(CLANG))
#define NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
#else
#define NO_SANITIZE_ADDRESS
#endif
const size_t asanMagic = 0xabefeed0;
const size_t asanDeferMemoryReuseCount = 2;
const size_t asanDeferMemoryReuseMask = 0x3;
#endif

View File

@ -6,15 +6,10 @@ visibility = ["//sky/engine/*"]
source_set("heap") {
sources = [
"AddressSanitizer.h",
"Handle.h",
"ThreadState.h",
"Visitor.h",
]
configs += [ "//sky/engine:config" ]
deps = [
"//third_party/icu",
]
}

View File

@ -1,42 +0,0 @@
#
# Copyright (C) 2013 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
{
'conditions': [
['OS=="android"', {
'variables': {
'isolate_dependency_tracked': [
],
'isolate_dependency_untracked': [
],
},
}],
],
}

View File

@ -1,3 +0,0 @@
include_rules = [
"+heap",
]

View File

@ -31,14 +31,13 @@
#ifndef Handle_h
#define Handle_h
#include "platform/heap/ThreadState.h"
#include "platform/heap/Visitor.h"
#include "wtf/Functional.h"
#include "wtf/HashFunctions.h"
#include "wtf/Locker.h"
#include "wtf/PassOwnPtr.h"
#include "wtf/RawPtr.h"
#include "wtf/RefCounted.h"
#include "wtf/TypeTraits.h"
#include "wtf/text/AtomicString.h"
// Classes that contain heap references but aren't themselves heap
// allocated, have some extra macros available which allows their use
@ -98,529 +97,27 @@
namespace blink {
template<typename T> class HeapTerminatedArray;
template<typename T> class Member;
class PersistentNode {
class Visitor {
public:
explicit PersistentNode(TraceCallback trace)
: m_trace(trace)
template<typename T>
void mark(T* t)
{
}
bool isAlive() { return m_trace; }
virtual ~PersistentNode()
{
ASSERT(isAlive());
m_trace = 0;
}
// Ideally the trace method should be virtual and automatically dispatch
// to the most specific implementation. However having a virtual method
// on PersistentNode leads to too eager template instantiation with MSVC
// which leads to include cycles.
// Instead we call the constructor with a TraceCallback which knows the
// type of the most specific child and calls trace directly. See
// TraceMethodDelegate in Visitor.h for how this is done.
void trace(Visitor* visitor)
{
m_trace(visitor, this);
}
protected:
TraceCallback m_trace;
private:
PersistentNode* m_next;
PersistentNode* m_prev;
template<typename RootsAccessor, typename Owner> friend class PersistentBase;
friend class PersistentAnchor;
};
// RootsAccessor for Persistent that provides access to thread-local list
// of persistent handles. Can only be used to create handles that
// are constructed and destructed on the same thread.
template<ThreadAffinity Affinity>
class ThreadLocalPersistents {
public:
static PersistentNode* roots() { return state()->roots(); }
// No locking required. Just check that we are at the right thread.
class Lock {
public:
Lock() { state()->checkThread(); }
};
private:
static ThreadState* state() { return ThreadStateFor<Affinity>::state(); }
};
// Base class for persistent handles. RootsAccessor specifies which list to
// link resulting handle into. Owner specifies the class containing trace
// method.
template<typename RootsAccessor, typename Owner>
class PersistentBase : public PersistentNode {
public:
~PersistentBase()
{
typename RootsAccessor::Lock lock;
ASSERT(m_roots == RootsAccessor::roots()); // Check that the thread is using the same roots list.
ASSERT(isAlive());
ASSERT(m_next->isAlive());
ASSERT(m_prev->isAlive());
m_next->m_prev = m_prev;
m_prev->m_next = m_next;
}
protected:
inline PersistentBase()
: PersistentNode(TraceMethodDelegate<Owner, &Owner::trace>::trampoline)
#if ENABLE(ASSERT)
, m_roots(RootsAccessor::roots())
#endif
{
typename RootsAccessor::Lock lock;
m_prev = RootsAccessor::roots();
m_next = m_prev->m_next;
m_prev->m_next = this;
m_next->m_prev = this;
}
inline explicit PersistentBase(const PersistentBase& otherref)
: PersistentNode(otherref.m_trace)
#if ENABLE(ASSERT)
, m_roots(RootsAccessor::roots())
#endif
{
// We don't support allocation of thread local Persistents while doing
// thread shutdown/cleanup.
typename RootsAccessor::Lock lock;
ASSERT(otherref.m_roots == m_roots); // Handles must belong to the same list.
PersistentBase* other = const_cast<PersistentBase*>(&otherref);
m_prev = other;
m_next = other->m_next;
other->m_next = this;
m_next->m_prev = this;
}
inline PersistentBase& operator=(const PersistentBase& otherref) { return *this; }
#if ENABLE(ASSERT)
private:
PersistentNode* m_roots;
#endif
};
// A dummy Persistent handle that ensures the list of persistents is never null.
// This removes a test from a hot path.
class PersistentAnchor : public PersistentNode {
public:
void trace(Visitor* visitor)
{
for (PersistentNode* current = m_next; current != this; current = current->m_next)
current->trace(visitor);
}
int numberOfPersistents()
{
int numberOfPersistents = 0;
for (PersistentNode* current = m_next; current != this; current = current->m_next)
++numberOfPersistents;
return numberOfPersistents;
}
virtual ~PersistentAnchor()
{
// FIXME: oilpan: Ideally we should have no left-over persistents at this point. However currently there is a
// large number of objects leaked when we tear down the main thread. Since some of these might contain a
// persistent or e.g. be RefCountedGarbageCollected we cannot guarantee there are no remaining Persistents at
// this point.
}
private:
PersistentAnchor() : PersistentNode(TraceMethodDelegate<PersistentAnchor, &PersistentAnchor::trace>::trampoline)
{
m_next = this;
m_prev = this;
}
friend class ThreadState;
};
// Persistent handles are used to store pointers into the
// managed heap. As long as the Persistent handle is alive
// the GC will keep the object pointed to alive. Persistent
// handles can be stored in objects and they are not scoped.
// Persistent handles must not be used to contain pointers
// between objects that are in the managed heap. They are only
// meant to point to managed heap objects from variables/members
// outside the managed heap.
//
// A Persistent is always a GC root from the point of view of
// the garbage collector.
//
// We have to construct and destruct Persistent with default RootsAccessor in
// the same thread.
template<typename T, typename RootsAccessor = ThreadLocalPersistents<ThreadingTrait<T>::Affinity > >
class Persistent : public PersistentBase<RootsAccessor, Persistent<T, RootsAccessor> > {
WTF_DISALLOW_CONSTRUCTION_FROM_ZERO(Persistent);
WTF_DISALLOW_ZERO_ASSIGNMENT(Persistent);
public:
Persistent() : m_raw(0) { }
Persistent(std::nullptr_t) : m_raw(0) { }
Persistent(T* raw) : m_raw(raw)
{
recordBacktrace();
}
explicit Persistent(T& raw) : m_raw(&raw)
{
recordBacktrace();
}
Persistent(const Persistent& other) : m_raw(other) { recordBacktrace(); }
template<typename U>
Persistent(const Persistent<U, RootsAccessor>& other) : m_raw(other) { recordBacktrace(); }
template<typename U>
Persistent(const Member<U>& other) : m_raw(other) { recordBacktrace(); }
template<typename U>
Persistent(const RawPtr<U>& other) : m_raw(other.get()) { recordBacktrace(); }
template<typename U>
Persistent& operator=(U* other)
{
m_raw = other;
recordBacktrace();
return *this;
}
Persistent& operator=(std::nullptr_t)
{
m_raw = 0;
return *this;
}
void clear() { m_raw = 0; }
virtual ~Persistent()
{
m_raw = 0;
}
template<typename U>
U* as() const
{
return static_cast<U*>(m_raw);
}
void trace(Visitor* visitor)
{
#if ENABLE(GC_PROFILE_MARKING)
visitor->setHostInfo(this, m_tracingName.isEmpty() ? "Persistent" : m_tracingName);
#endif
visitor->mark(m_raw);
}
RawPtr<T> release()
{
RawPtr<T> result = m_raw;
m_raw = 0;
return result;
}
T& operator*() const { return *m_raw; }
bool operator!() const { return !m_raw; }
operator T*() const { return m_raw; }
operator RawPtr<T>() const { return m_raw; }
T* operator->() const { return *this; }
Persistent& operator=(const Persistent& other)
{
m_raw = other;
recordBacktrace();
return *this;
}
template<typename U>
Persistent& operator=(const Persistent<U, RootsAccessor>& other)
{
m_raw = other;
recordBacktrace();
return *this;
}
template<typename U>
Persistent& operator=(const Member<U>& other)
{
m_raw = other;
recordBacktrace();
return *this;
}
template<typename U>
Persistent& operator=(const RawPtr<U>& other)
{
m_raw = other;
recordBacktrace();
return *this;
}
T* get() const { return m_raw; }
private:
inline void recordBacktrace() const { }
T* m_raw;
};
// Members are used in classes to contain strong pointers to other oilpan heap
// allocated objects.
// All Member fields of a class must be traced in the class' trace method.
// During the mark phase of the GC all live objects are marked as live and
// all Member fields of a live object will be traced marked as live as well.
template<typename T>
class Member {
WTF_DISALLOW_CONSTRUCTION_FROM_ZERO(Member);
WTF_DISALLOW_ZERO_ASSIGNMENT(Member);
public:
Member() : m_raw(0)
template<typename T>
void trace(const T* t)
{
}
Member(std::nullptr_t) : m_raw(0)
template<typename T>
void trace(T* t)
{
}
Member(T* raw) : m_raw(raw)
{
}
explicit Member(T& raw) : m_raw(&raw)
{
}
template<typename U>
Member(const RawPtr<U>& other) : m_raw(other.get())
{
}
Member(WTF::HashTableDeletedValueType) : m_raw(reinterpret_cast<T*>(-1))
{
}
bool isHashTableDeletedValue() const { return m_raw == reinterpret_cast<T*>(-1); }
template<typename U>
Member(const Persistent<U>& other) : m_raw(other) { }
Member(const Member& other) : m_raw(other) { }
template<typename U>
Member(const Member<U>& other) : m_raw(other) { }
T* release()
{
T* result = m_raw;
m_raw = 0;
return result;
}
template<typename U>
U* as() const
{
return static_cast<U*>(m_raw);
}
bool operator!() const { return !m_raw; }
operator T*() const { return m_raw; }
T* operator->() const { return m_raw; }
T& operator*() const { return *m_raw; }
template<typename U>
operator RawPtr<U>() const { return m_raw; }
template<typename U>
Member& operator=(const Persistent<U>& other)
{
m_raw = other;
return *this;
}
template<typename U>
Member& operator=(const Member<U>& other)
{
m_raw = other;
return *this;
}
template<typename U>
Member& operator=(U* other)
{
m_raw = other;
return *this;
}
template<typename U>
Member& operator=(RawPtr<U> other)
{
m_raw = other;
return *this;
}
Member& operator=(std::nullptr_t)
{
m_raw = 0;
return *this;
}
void swap(Member<T>& other) { std::swap(m_raw, other.m_raw); }
T* get() const { return m_raw; }
void clear() { m_raw = 0; }
protected:
void verifyTypeIsGarbageCollected() const
{
}
T* m_raw;
friend class Visitor;
};
template<typename T>
class TraceTrait<Member<T> > {
public:
static void trace(Visitor* visitor, void* self)
{
TraceTrait<T>::mark(visitor, *static_cast<Member<T>*>(self));
}
};
// TraceTrait to allow compilation of trace method bodies when oilpan is disabled.
// This should never be called, but is needed to compile.
template<typename T>
class TraceTrait<RefPtr<T> > {
public:
static void trace(Visitor*, void*)
{
ASSERT_NOT_REACHED();
}
};
template<typename T>
class TraceTrait<OwnPtr<T> > {
public:
static void trace(Visitor* visitor, OwnPtr<T>* ptr)
{
ASSERT_NOT_REACHED();
}
};
template <typename T> struct RemoveHeapPointerWrapperTypes {
typedef typename WTF::RemoveTemplate<typename WTF::RemoveTemplate<typename WTF::RemoveTemplate<T, Member>::Type, WeakMember>::Type, RawPtr>::Type Type;
};
// This trace trait for std::pair will null weak members if their referent is
// collected. If you have a collection that contain weakness it does not remove
// entries from the collection that contain nulled weak members.
template<typename T, typename U>
class TraceTrait<std::pair<T, U> > {
public:
static void trace(Visitor* visitor, std::pair<T, U>* pair)
template<typename T>
void trace(const T& t)
{
}
};
// WeakMember is similar to Member in that it is used to point to other oilpan
// heap allocated objects.
// However instead of creating a strong pointer to the object, the WeakMember creates
// a weak pointer, which does not keep the pointee alive. Hence if all pointers to
// to a heap allocated object are weak the object will be garbage collected. At the
// time of GC the weak pointers will automatically be set to null.
template<typename T>
class WeakMember : public Member<T> {
WTF_DISALLOW_CONSTRUCTION_FROM_ZERO(WeakMember);
WTF_DISALLOW_ZERO_ASSIGNMENT(WeakMember);
public:
WeakMember() : Member<T>() { }
WeakMember(std::nullptr_t) : Member<T>(nullptr) { }
WeakMember(T* raw) : Member<T>(raw) { }
WeakMember(WTF::HashTableDeletedValueType x) : Member<T>(x) { }
template<typename U>
WeakMember(const Persistent<U>& other) : Member<T>(other) { }
template<typename U>
WeakMember(const Member<U>& other) : Member<T>(other) { }
template<typename U>
WeakMember& operator=(const Persistent<U>& other)
{
this->m_raw = other;
return *this;
}
template<typename U>
WeakMember& operator=(const Member<U>& other)
{
this->m_raw = other;
return *this;
}
template<typename U>
WeakMember& operator=(U* other)
{
this->m_raw = other;
return *this;
}
template<typename U>
WeakMember& operator=(const RawPtr<U>& other)
{
this->m_raw = other;
return *this;
}
WeakMember& operator=(std::nullptr_t)
{
this->m_raw = 0;
return *this;
}
private:
T** cell() const { return const_cast<T**>(&this->m_raw); }
friend class Visitor;
};
// Comparison operators between (Weak)Members and Persistents
template<typename T, typename U> inline bool operator==(const Member<T>& a, const Member<U>& b) { return a.get() == b.get(); }
template<typename T, typename U> inline bool operator!=(const Member<T>& a, const Member<U>& b) { return a.get() != b.get(); }
template<typename T, typename U> inline bool operator==(const Member<T>& a, const Persistent<U>& b) { return a.get() == b.get(); }
template<typename T, typename U> inline bool operator!=(const Member<T>& a, const Persistent<U>& b) { return a.get() != b.get(); }
template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Member<U>& b) { return a.get() == b.get(); }
template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Member<U>& b) { return a.get() != b.get(); }
template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Persistent<U>& b) { return a.get() == b.get(); }
template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Persistent<U>& b) { return a.get() != b.get(); }
#define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TYPE)
template<typename T>
class DummyBase {
@ -649,129 +146,6 @@ public:
namespace WTF {
template <typename T> struct VectorTraits<blink::Member<T> > : VectorTraitsBase<blink::Member<T> > {
static const bool needsDestruction = false;
static const bool canInitializeWithMemset = true;
static const bool canMoveWithMemcpy = true;
};
template <typename T> struct VectorTraits<blink::WeakMember<T> > : VectorTraitsBase<blink::WeakMember<T> > {
static const bool needsDestruction = false;
static const bool canInitializeWithMemset = true;
static const bool canMoveWithMemcpy = true;
};
template<typename T> struct HashTraits<blink::Member<T> > : SimpleClassHashTraits<blink::Member<T> > {
static const bool needsDestruction = false;
// FIXME: The distinction between PeekInType and PassInType is there for
// the sake of the reference counting handles. When they are gone the two
// types can be merged into PassInType.
// FIXME: Implement proper const'ness for iterator types. Requires support
// in the marking Visitor.
typedef RawPtr<T> PeekInType;
typedef RawPtr<T> PassInType;
typedef blink::Member<T>* IteratorGetType;
typedef const blink::Member<T>* IteratorConstGetType;
typedef blink::Member<T>& IteratorReferenceType;
typedef T* const IteratorConstReferenceType;
static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { return *x; }
static IteratorConstReferenceType getToReferenceConstConversion(IteratorConstGetType x) { return x->get(); }
// FIXME: Similarly, there is no need for a distinction between PeekOutType
// and PassOutType without reference counting.
typedef T* PeekOutType;
typedef T* PassOutType;
template<typename U>
static void store(const U& value, blink::Member<T>& storage) { storage = value; }
static PeekOutType peek(const blink::Member<T>& value) { return value; }
static PassOutType passOut(const blink::Member<T>& value) { return value; }
};
template<typename T> struct HashTraits<blink::WeakMember<T> > : SimpleClassHashTraits<blink::WeakMember<T> > {
static const bool needsDestruction = false;
// FIXME: The distinction between PeekInType and PassInType is there for
// the sake of the reference counting handles. When they are gone the two
// types can be merged into PassInType.
// FIXME: Implement proper const'ness for iterator types. Requires support
// in the marking Visitor.
typedef RawPtr<T> PeekInType;
typedef RawPtr<T> PassInType;
typedef blink::WeakMember<T>* IteratorGetType;
typedef const blink::WeakMember<T>* IteratorConstGetType;
typedef blink::WeakMember<T>& IteratorReferenceType;
typedef T* const IteratorConstReferenceType;
static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { return *x; }
static IteratorConstReferenceType getToReferenceConstConversion(IteratorConstGetType x) { return x->get(); }
// FIXME: Similarly, there is no need for a distinction between PeekOutType
// and PassOutType without reference counting.
typedef T* PeekOutType;
typedef T* PassOutType;
template<typename U>
static void store(const U& value, blink::WeakMember<T>& storage) { storage = value; }
static PeekOutType peek(const blink::WeakMember<T>& value) { return value; }
static PassOutType passOut(const blink::WeakMember<T>& value) { return value; }
static bool traceInCollection(blink::Visitor* visitor, blink::WeakMember<T>& weakMember, ShouldWeakPointersBeMarkedStrongly strongify)
{
}
};
template<typename T> struct PtrHash<blink::Member<T> > : PtrHash<T*> {
template<typename U>
static unsigned hash(const U& key) { return PtrHash<T*>::hash(key); }
static bool equal(T* a, const blink::Member<T>& b) { return a == b; }
static bool equal(const blink::Member<T>& a, T* b) { return a == b; }
template<typename U, typename V>
static bool equal(const U& a, const V& b) { return a == b; }
};
template<typename T> struct PtrHash<blink::WeakMember<T> > : PtrHash<blink::Member<T> > {
};
template<typename P> struct PtrHash<blink::Persistent<P> > : PtrHash<P*> {
using PtrHash<P*>::hash;
static unsigned hash(const RefPtr<P>& key) { return hash(key.get()); }
using PtrHash<P*>::equal;
static bool equal(const RefPtr<P>& a, const RefPtr<P>& b) { return a == b; }
static bool equal(P* a, const RefPtr<P>& b) { return a == b; }
static bool equal(const RefPtr<P>& a, P* b) { return a == b; }
};
// PtrHash is the default hash for hash tables with members.
template<typename T> struct DefaultHash<blink::Member<T> > {
typedef PtrHash<blink::Member<T> > Hash;
};
template<typename T> struct DefaultHash<blink::WeakMember<T> > {
typedef PtrHash<blink::WeakMember<T> > Hash;
};
template<typename T> struct DefaultHash<blink::Persistent<T> > {
typedef PtrHash<blink::Persistent<T> > Hash;
};
template<typename T>
struct NeedsTracing<blink::Member<T> > {
static const bool value = true;
};
template<typename T>
struct IsWeak<blink::WeakMember<T> > {
static const bool value = true;
};
template<typename T> inline T* getPtr(const blink::Member<T>& p)
{
return p.get();
}
template<typename T> inline T* getPtr(const blink::Persistent<T>& p)
{
return p.get();
}
// For wtf/Functional.h
template<typename T, bool isGarbageCollected> struct PointerParamStorageTraits;

View File

@ -1,742 +0,0 @@
/*
* Copyright (C) 2013 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef ThreadState_h
#define ThreadState_h
#include "platform/PlatformExport.h"
#include "platform/heap/AddressSanitizer.h"
#include "public/platform/WebThread.h"
#include "wtf/HashSet.h"
#include "wtf/OwnPtr.h"
#include "wtf/PassOwnPtr.h"
#include "wtf/ThreadSpecific.h"
#include "wtf/Threading.h"
#include "wtf/ThreadingPrimitives.h"
#include "wtf/Vector.h"
#if ENABLE(GC_PROFILE_HEAP)
#include "wtf/HashMap.h"
#endif
namespace blink {
class BaseHeap;
class BaseHeapPage;
class FinalizedHeapObjectHeader;
struct GCInfo;
class HeapContainsCache;
class HeapObjectHeader;
class PageMemory;
class PersistentNode;
class Visitor;
class SafePointBarrier;
class SafePointAwareMutexLocker;
template<typename Header> class ThreadHeap;
class CallbackStack;
typedef uint8_t* Address;
typedef void (*FinalizationCallback)(void*);
typedef void (*VisitorCallback)(Visitor*, void* self);
typedef VisitorCallback TraceCallback;
typedef VisitorCallback WeakPointerCallback;
typedef VisitorCallback EphemeronCallback;
// ThreadAffinity indicates which threads objects can be used on. We
// distinguish between objects that can be used on the main thread
// only and objects that can be used on any thread.
//
// For objects that can only be used on the main thread we avoid going
// through thread-local storage to get to the thread state.
//
// FIXME: We should evaluate the performance gain. Having
// ThreadAffinity is complicating the implementation and we should get
// rid of it if it is fast enough to go through thread-local storage
// always.
enum ThreadAffinity {
AnyThread,
MainThreadOnly,
};
class Node;
class CSSValue;
template<typename T, bool derivesNode = WTF::IsSubclass<typename WTF::RemoveConst<T>::Type, Node>::value> struct DefaultThreadingTrait;
template<typename T>
struct DefaultThreadingTrait<T, false> {
static const ThreadAffinity Affinity = AnyThread;
};
template<typename T>
struct DefaultThreadingTrait<T, true> {
static const ThreadAffinity Affinity = MainThreadOnly;
};
template<typename T>
struct ThreadingTrait {
static const ThreadAffinity Affinity = DefaultThreadingTrait<T>::Affinity;
};
// Marks the specified class as being used from multiple threads. When
// a class is used from multiple threads we go through thread local
// storage to get the heap in which to allocate an object of that type
// and when allocating a Persistent handle for an object with that
// type. Notice that marking the base class does not automatically
// mark its descendants and they have to be explicitly marked.
#define USED_FROM_MULTIPLE_THREADS(Class) \
class Class; \
template<> struct ThreadingTrait<Class> { \
static const ThreadAffinity Affinity = AnyThread; \
}
#define USED_FROM_MULTIPLE_THREADS_NAMESPACE(Namespace, Class) \
namespace Namespace { \
class Class; \
} \
namespace blink { \
template<> struct ThreadingTrait<Namespace::Class> { \
static const ThreadAffinity Affinity = AnyThread; \
}; \
}
template<typename U> class ThreadingTrait<const U> : public ThreadingTrait<U> { };
// List of typed heaps. The list is used to generate the implementation
// of typed heap related methods.
//
// To create a new typed heap add a H(<ClassName>) to the
// FOR_EACH_TYPED_HEAP macro below.
#define FOR_EACH_TYPED_HEAP(H) \
H(Node)
#define TypedHeapEnumName(Type) Type##Heap,
#define TypedHeapEnumNameNonFinalized(Type) Type##HeapNonFinalized,
enum TypedHeaps {
GeneralHeap = 0,
CollectionBackingHeap,
FOR_EACH_TYPED_HEAP(TypedHeapEnumName)
GeneralHeapNonFinalized,
CollectionBackingHeapNonFinalized,
FOR_EACH_TYPED_HEAP(TypedHeapEnumNameNonFinalized)
// Values used for iteration of heap segments.
NumberOfHeaps,
FirstFinalizedHeap = GeneralHeap,
FirstNonFinalizedHeap = GeneralHeapNonFinalized,
NumberOfFinalizedHeaps = GeneralHeapNonFinalized,
NumberOfNonFinalizedHeaps = NumberOfHeaps - NumberOfFinalizedHeaps,
NonFinalizedHeapOffset = FirstNonFinalizedHeap
};
// Base implementation for HeapIndexTrait found below.
template<int heapIndex>
struct HeapIndexTraitBase {
typedef FinalizedHeapObjectHeader HeaderType;
typedef ThreadHeap<HeaderType> HeapType;
static const int finalizedIndex = heapIndex;
static const int nonFinalizedIndex = heapIndex + static_cast<int>(NonFinalizedHeapOffset);
static int index(bool isFinalized)
{
return isFinalized ? finalizedIndex : nonFinalizedIndex;
}
};
// HeapIndexTrait defines properties for each heap in the TypesHeaps enum.
template<int index>
struct HeapIndexTrait;
template<>
struct HeapIndexTrait<GeneralHeap> : public HeapIndexTraitBase<GeneralHeap> { };
template<>
struct HeapIndexTrait<GeneralHeapNonFinalized> : public HeapIndexTrait<GeneralHeap> { };
template<>
struct HeapIndexTrait<CollectionBackingHeap> : public HeapIndexTraitBase<CollectionBackingHeap> { };
template<>
struct HeapIndexTrait<CollectionBackingHeapNonFinalized> : public HeapIndexTrait<CollectionBackingHeap> { };
#define DEFINE_TYPED_HEAP_INDEX_TRAIT(Type) \
template<> \
struct HeapIndexTrait<Type##Heap> : public HeapIndexTraitBase<Type##Heap> { \
typedef HeapObjectHeader HeaderType; \
typedef ThreadHeap<HeaderType> HeapType; \
}; \
template<> \
struct HeapIndexTrait<Type##HeapNonFinalized> : public HeapIndexTrait<Type##Heap> { };
FOR_EACH_TYPED_HEAP(DEFINE_TYPED_HEAP_INDEX_TRAIT)
#undef DEFINE_TYPED_HEAP_INDEX_TRAIT
// HeapTypeTrait defines which heap to use for particular types.
// By default objects are allocated in the GeneralHeap.
template<typename T>
struct HeapTypeTrait : public HeapIndexTrait<GeneralHeap> { };
// We don't have any type-based mappings to the CollectionBackingHeap.
// Each typed-heap maps the respective type to its heap.
#define DEFINE_TYPED_HEAP_TRAIT(Type) \
class Type; \
template<> \
struct HeapTypeTrait<class Type> : public HeapIndexTrait<Type##Heap> { };
FOR_EACH_TYPED_HEAP(DEFINE_TYPED_HEAP_TRAIT)
#undef DEFINE_TYPED_HEAP_TRAIT
// A HeapStats structure keeps track of the amount of memory allocated
// for a Blink heap and how much of that memory is used for actual
// Blink objects. These stats are used in the heuristics to determine
// when to perform garbage collections.
class HeapStats {
public:
HeapStats() : m_totalObjectSpace(0), m_totalAllocatedSpace(0) { }
size_t totalObjectSpace() const { return m_totalObjectSpace; }
size_t totalAllocatedSpace() const { return m_totalAllocatedSpace; }
void add(HeapStats* other)
{
m_totalObjectSpace += other->m_totalObjectSpace;
m_totalAllocatedSpace += other->m_totalAllocatedSpace;
}
void inline increaseObjectSpace(size_t newObjectSpace)
{
m_totalObjectSpace += newObjectSpace;
}
void inline decreaseObjectSpace(size_t deadObjectSpace)
{
m_totalObjectSpace -= deadObjectSpace;
}
void inline increaseAllocatedSpace(size_t newAllocatedSpace)
{
m_totalAllocatedSpace += newAllocatedSpace;
}
void inline decreaseAllocatedSpace(size_t deadAllocatedSpace)
{
m_totalAllocatedSpace -= deadAllocatedSpace;
}
void clear()
{
m_totalObjectSpace = 0;
m_totalAllocatedSpace = 0;
}
bool operator==(const HeapStats& other)
{
return m_totalAllocatedSpace == other.m_totalAllocatedSpace
&& m_totalObjectSpace == other.m_totalObjectSpace;
}
private:
size_t m_totalObjectSpace; // Actually contains objects that may be live, not including headers.
size_t m_totalAllocatedSpace; // Allocated from the OS.
friend class HeapTester;
};
class PLATFORM_EXPORT ThreadState {
WTF_MAKE_NONCOPYABLE(ThreadState);
public:
// When garbage collecting we need to know whether or not there
// can be pointers to Blink GC managed objects on the stack for
// each thread. When threads reach a safe point they record
// whether or not they have pointers on the stack.
enum StackState {
NoHeapPointersOnStack,
HeapPointersOnStack
};
class NoSweepScope {
public:
explicit NoSweepScope(ThreadState* state) : m_state(state)
{
ASSERT(!m_state->m_sweepInProgress);
m_state->m_sweepInProgress = true;
}
~NoSweepScope()
{
ASSERT(m_state->m_sweepInProgress);
m_state->m_sweepInProgress = false;
}
private:
ThreadState* m_state;
};
// The set of ThreadStates for all threads attached to the Blink
// garbage collector.
typedef HashSet<ThreadState*> AttachedThreadStateSet;
static AttachedThreadStateSet& attachedThreads();
bool isTerminating() { return m_isTerminating; }
// Trace all persistent roots, called when marking the managed heap objects.
static void visitPersistentRoots(Visitor*);
// Trace all objects found on the stack, used when doing conservative GCs.
static void visitStackRoots(Visitor*);
// Associate ThreadState object with the current thread. After this
// call thread can start using the garbage collected heap infrastructure.
// It also has to periodically check for safepoints.
static void attach();
// Disassociate attached ThreadState from the current thread. The thread
// can no longer use the garbage collected heap after this call.
static void detach();
static ThreadState* mainThreadState()
{
return reinterpret_cast<ThreadState*>(s_mainThreadStateStorage);
}
bool isMainThread() const { return this == mainThreadState(); }
inline bool checkThread() const
{
ASSERT(m_thread == currentThread());
return true;
}
// shouldGC and shouldForceConservativeGC implement the heuristics
// that are used to determine when to collect garbage. If
// shouldForceConservativeGC returns true, we force the garbage
// collection immediately. Otherwise, if shouldGC returns true, we
// record that we should garbage collect the next time we return
// to the event loop. If both return false, we don't need to
// collect garbage at this point.
bool shouldGC();
bool shouldForceConservativeGC();
bool increasedEnoughToGC(size_t, size_t);
bool increasedEnoughToForceConservativeGC(size_t, size_t);
// If gcRequested returns true when a thread returns to its event
// loop the thread will initiate a garbage collection.
bool gcRequested();
void setGCRequested();
void clearGCRequested();
// Was the last GC forced for testing? This is set when garbage collection
// is forced for testing and there are pointers on the stack. It remains
// set until a garbage collection is triggered with no pointers on the stack.
// This is used for layout tests that trigger GCs and check if objects are
// dead at a given point in time. That only reliably works when we get
// precise GCs with no conservative stack scanning.
void setForcePreciseGCForTesting(bool);
bool forcePreciseGCForTesting();
bool sweepRequested();
void setSweepRequested();
void clearSweepRequested();
void performPendingSweep();
// Support for disallowing allocation. Mainly used for sanity
// checks asserts.
bool isAllocationAllowed() const { return !isAtSafePoint() && !m_noAllocationCount; }
void enterNoAllocationScope() { m_noAllocationCount++; }
void leaveNoAllocationScope() { m_noAllocationCount--; }
// Before performing GC the thread-specific heap state should be
// made consistent for sweeping.
void makeConsistentForSweeping();
#if ENABLE(ASSERT)
bool isConsistentForSweeping();
#endif
// Is the thread corresponding to this thread state currently
// performing GC?
bool isInGC() const { return m_inGC; }
// Is any of the threads registered with the blink garbage collection
// infrastructure currently performing GC?
static bool isAnyThreadInGC() { return s_inGC; }
void enterGC()
{
ASSERT(!m_inGC);
ASSERT(!s_inGC);
m_inGC = true;
s_inGC = true;
}
void leaveGC()
{
m_inGC = false;
s_inGC = false;
}
// Is the thread corresponding to this thread state currently
// sweeping?
bool isSweepInProgress() const { return m_sweepInProgress; }
void prepareForGC();
// Safepoint related functionality.
//
// When a thread attempts to perform GC it needs to stop all other threads
// that use the heap or at least guarantee that they will not touch any
// heap allocated object until GC is complete.
//
// We say that a thread is at a safepoint if this thread is guaranteed to
// not touch any heap allocated object or any heap related functionality until
// it leaves the safepoint.
//
// Notice that a thread does not have to be paused if it is at safepoint it
// can continue to run and perform tasks that do not require interaction
// with the heap. It will be paused if it attempts to leave the safepoint and
// there is a GC in progress.
//
// Each thread that has ThreadState attached must:
// - periodically check if GC is requested from another thread by calling a safePoint() method;
// - use SafePointScope around long running loops that have no safePoint() invocation inside,
// such loops must not touch any heap object;
// - register an Interruptor that can interrupt long running loops that have no calls to safePoint and
// are not wrapped in a SafePointScope (e.g. Interruptor for JavaScript code)
//
// Request all other threads to stop. Must only be called if the current thread is at safepoint.
static bool stopThreads();
static void resumeThreads();
// Check if GC is requested by another thread and pause this thread if this is the case.
// Can only be called when current thread is in a consistent state.
void safePoint(StackState);
// Mark current thread as running inside safepoint.
void enterSafePointWithoutPointers() { enterSafePoint(NoHeapPointersOnStack, 0); }
void enterSafePointWithPointers(void* scopeMarker) { enterSafePoint(HeapPointersOnStack, scopeMarker); }
void leaveSafePoint(SafePointAwareMutexLocker* = 0);
bool isAtSafePoint() const { return m_atSafePoint; }
// If attached thread enters long running loop that can call back
// into Blink and leaving and reentering safepoint at every
// transition between this loop and Blink is deemed too expensive
// then instead of marking this loop as a GC safepoint thread
// can provide an interruptor object which would allow GC
// to temporarily interrupt and pause this long running loop at
// an arbitrary moment creating a safepoint for a GC.
class PLATFORM_EXPORT Interruptor {
public:
virtual ~Interruptor() { }
// Request the interruptor to interrupt the thread and
// call onInterrupted on that thread once interruption
// succeeds.
virtual void requestInterrupt() = 0;
// Clear previous interrupt request.
virtual void clearInterrupt() = 0;
protected:
// This method is called on the interrupted thread to
// create a safepoint for a GC.
void onInterrupted();
};
void addInterruptor(Interruptor*);
void removeInterruptor(Interruptor*);
// CleanupTasks are executed when ThreadState performs
// cleanup before detaching.
class CleanupTask {
public:
virtual ~CleanupTask() { }
// Executed before the final GC.
virtual void preCleanup() { }
// Executed after the final GC. Thread heap is empty at this point.
virtual void postCleanup() { }
};
void addCleanupTask(PassOwnPtr<CleanupTask> cleanupTask)
{
m_cleanupTasks.append(cleanupTask);
}
// Should only be called under protection of threadAttachMutex().
const Vector<Interruptor*>& interruptors() const { return m_interruptors; }
void recordStackEnd(intptr_t* endOfStack)
{
m_endOfStack = endOfStack;
}
// Get one of the heap structures for this thread.
//
// The heap is split into multiple heap parts based on object
// types. To get the index for a given type, use
// HeapTypeTrait<Type>::index.
BaseHeap* heap(int index) const { return m_heaps[index]; }
// Infrastructure to determine if an address is within one of the
// address ranges for the Blink heap. If the address is in the Blink
// heap the containing heap page is returned.
HeapContainsCache* heapContainsCache() { return m_heapContainsCache.get(); }
BaseHeapPage* contains(Address address) { return heapPageFromAddress(address); }
BaseHeapPage* contains(void* pointer) { return contains(reinterpret_cast<Address>(pointer)); }
BaseHeapPage* contains(const void* pointer) { return contains(const_cast<void*>(pointer)); }
// List of persistent roots allocated on the given thread.
PersistentNode* roots() const { return m_persistents.get(); }
// List of global persistent roots not owned by any particular thread.
// globalRootsMutex must be acquired before any modifications.
static PersistentNode* globalRoots();
static Mutex& globalRootsMutex();
// Visit local thread stack and trace all pointers conservatively.
void visitStack(Visitor*);
// Visit the asan fake stack frame corresponding to a slot on the
// real machine stack if there is one.
void visitAsanFakeStackForPointer(Visitor*, Address);
// Visit all persistents allocated on this thread.
void visitPersistents(Visitor*);
// Checks a given address and if a pointer into the oilpan heap marks
// the object to which it points.
bool checkAndMarkPointer(Visitor*, Address);
#if ENABLE(GC_PROFILE_MARKING)
const GCInfo* findGCInfo(Address);
static const GCInfo* findGCInfoFromAllThreads(Address);
#endif
#if ENABLE(GC_PROFILE_HEAP)
struct SnapshotInfo {
ThreadState* state;
size_t freeSize;
size_t pageCount;
// Map from base-classes to a snapshot class-ids (used as index below).
HashMap<const GCInfo*, size_t> classTags;
// Map from class-id (index) to count/size.
Vector<int> liveCount;
Vector<int> deadCount;
Vector<size_t> liveSize;
Vector<size_t> deadSize;
// Map from class-id (index) to a vector of generation counts.
// For i < 7, the count is the number of objects that died after surviving |i| GCs.
// For i == 7, the count is the number of objects that survived at least 7 GCs.
Vector<Vector<int, 8> > generations;
explicit SnapshotInfo(ThreadState* state) : state(state), freeSize(0), pageCount(0) { }
size_t getClassTag(const GCInfo*);
};
void snapshot();
#endif
void pushWeakObjectPointerCallback(void*, WeakPointerCallback);
bool popAndInvokeWeakPointerCallback(Visitor*);
void getStats(HeapStats&);
HeapStats& stats() { return m_stats; }
HeapStats& statsAfterLastGC() { return m_statsAfterLastGC; }
void setupHeapsForTermination();
void registerSweepingTask();
void unregisterSweepingTask();
Mutex& sweepMutex() { return m_sweepMutex; }
private:
explicit ThreadState();
~ThreadState();
friend class SafePointBarrier;
void enterSafePoint(StackState, void*);
NO_SANITIZE_ADDRESS void copyStackUntilSafePointScope();
void clearSafePointScopeMarker()
{
m_safePointStackCopy.clear();
m_safePointScopeMarker = 0;
}
void performPendingGC(StackState);
// Finds the Blink HeapPage in this thread-specific heap
// corresponding to a given address. Return 0 if the address is
// not contained in any of the pages. This does not consider
// large objects.
BaseHeapPage* heapPageFromAddress(Address);
// When ThreadState is detaching from non-main thread its
// heap is expected to be empty (because it is going away).
// Perform registered cleanup tasks and garbage collection
// to sweep away any objects that are left on this heap.
// We assert that nothing must remain after this cleanup.
// If assertion does not hold we crash as we are potentially
// in the dangling pointer situation.
void cleanup();
void cleanupPages();
void setLowCollectionRate(bool value) { m_lowCollectionRate = value; }
void waitUntilSweepersDone();
static WTF::ThreadSpecific<ThreadState*>* s_threadSpecific;
static SafePointBarrier* s_safePointBarrier;
// This variable is flipped to true after all threads are stoped
// and outermost GC has started.
static bool s_inGC;
// We can't create a static member of type ThreadState here
// because it will introduce global constructor and destructor.
// We would like to manage lifetime of the ThreadState attached
// to the main thread explicitly instead and still use normal
// constructor and destructor for the ThreadState class.
// For this we reserve static storage for the main ThreadState
// and lazily construct ThreadState in it using placement new.
static uint8_t s_mainThreadStateStorage[];
ThreadIdentifier m_thread;
OwnPtr<PersistentNode> m_persistents;
StackState m_stackState;
intptr_t* m_startOfStack;
intptr_t* m_endOfStack;
void* m_safePointScopeMarker;
Vector<Address> m_safePointStackCopy;
bool m_atSafePoint;
Vector<Interruptor*> m_interruptors;
bool m_gcRequested;
bool m_forcePreciseGCForTesting;
volatile int m_sweepRequested;
bool m_sweepInProgress;
size_t m_noAllocationCount;
bool m_inGC;
BaseHeap* m_heaps[NumberOfHeaps];
OwnPtr<HeapContainsCache> m_heapContainsCache;
HeapStats m_stats;
HeapStats m_statsAfterLastGC;
Vector<OwnPtr<CleanupTask> > m_cleanupTasks;
bool m_isTerminating;
bool m_lowCollectionRate;
OwnPtr<blink::WebThread> m_sweeperThread;
int m_numberOfSweeperTasks;
Mutex m_sweepMutex;
ThreadCondition m_sweepThreadCondition;
CallbackStack* m_weakCallbackStack;
#if defined(ADDRESS_SANITIZER)
void* m_asanFakeStack;
#endif
};
template<ThreadAffinity affinity> class ThreadStateFor;
template<> class ThreadStateFor<MainThreadOnly> {
public:
static ThreadState* state()
{
// This specialization must only be used from the main thread.
return ThreadState::mainThreadState();
}
};
template<> class ThreadStateFor<AnyThread> {
public:
static ThreadState* state() { return 0; }
};
// Common header for heap pages. Needs to be defined before class Visitor.
class BaseHeapPage {
public:
BaseHeapPage(PageMemory*, const GCInfo*, ThreadState*);
virtual ~BaseHeapPage() { }
// Check if the given address points to an object in this
// heap page. If so, find the start of that object and mark it
// using the given Visitor. Otherwise do nothing. The pointer must
// be within the same aligned blinkPageSize as the this-pointer.
//
// This is used during conservative stack scanning to
// conservatively mark all objects that could be referenced from
// the stack.
virtual void checkAndMarkPointer(Visitor*, Address) = 0;
virtual bool contains(Address) = 0;
#if ENABLE(GC_PROFILE_MARKING)
virtual const GCInfo* findGCInfo(Address) = 0;
#endif
Address address() { return reinterpret_cast<Address>(this); }
PageMemory* storage() const { return m_storage; }
ThreadState* threadState() const { return m_threadState; }
const GCInfo* gcInfo() { return m_gcInfo; }
virtual bool isLargeObject() { return false; }
virtual void markOrphaned()
{
m_threadState = 0;
m_gcInfo = 0;
m_terminating = false;
m_tracedAfterOrphaned = false;
}
bool orphaned() { return !m_threadState; }
bool terminating() { return m_terminating; }
void setTerminating() { m_terminating = true; }
bool tracedAfterOrphaned() { return m_tracedAfterOrphaned; }
void setTracedAfterOrphaned() { m_tracedAfterOrphaned = true; }
size_t promptlyFreedSize() { return m_promptlyFreedSize; }
void resetPromptlyFreedSize() { m_promptlyFreedSize = 0; }
void addToPromptlyFreedSize(size_t size) { m_promptlyFreedSize += size; }
private:
PageMemory* m_storage;
const GCInfo* m_gcInfo;
ThreadState* m_threadState;
// Pointer sized integer to ensure proper alignment of the
// HeapPage header. We use some of the bits to determine
// whether the page is part of a terminting thread or
// if the page is traced after being terminated (orphaned).
uintptr_t m_terminating : 1;
uintptr_t m_tracedAfterOrphaned : 1;
uintptr_t m_promptlyFreedSize : 17; // == blinkPageSizeLog2
};
}
#endif // ThreadState_h

View File

@ -1,601 +0,0 @@
/*
* Copyright (C) 2013 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef Visitor_h
#define Visitor_h
#include "platform/PlatformExport.h"
#include "platform/heap/ThreadState.h"
#include "wtf/Assertions.h"
#include "wtf/Deque.h"
#include "wtf/Forward.h"
#include "wtf/HashMap.h"
#include "wtf/HashTraits.h"
#include "wtf/InstanceCounter.h"
#include "wtf/OwnPtr.h"
#include "wtf/RefPtr.h"
#include "wtf/TypeTraits.h"
#include "wtf/WeakPtr.h"
#if ENABLE(GC_PROFILING)
#include "wtf/text/WTFString.h"
#endif
#if ENABLE(ASSERT)
#define DEBUG_ONLY(x) x
#else
#define DEBUG_ONLY(x)
#endif
namespace blink {
class FinalizedHeapObjectHeader;
template<typename T> class GarbageCollectedFinalized;
class HeapObjectHeader;
template<typename T> class Member;
template<typename T> class WeakMember;
class Visitor;
template<bool needsTracing, WTF::WeakHandlingFlag weakHandlingFlag, WTF::ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits> struct CollectionBackingTraceTrait;
// The TraceMethodDelegate is used to convert a trace method for type T to a TraceCallback.
// This allows us to pass a type's trace method as a parameter to the PersistentNode
// constructor. The PersistentNode constructor needs the specific trace method due an issue
// with the Windows compiler which instantiates even unused variables. This causes problems
// in header files where we have only forward declarations of classes.
template<typename T, void (T::*method)(Visitor*)>
struct TraceMethodDelegate {
static void trampoline(Visitor* visitor, void* self) { (reinterpret_cast<T*>(self)->*method)(visitor); }
};
// GCInfo contains meta-data associated with objects allocated in the
// Blink heap. This meta-data consists of a function pointer used to
// trace the pointers in the object during garbage collection, an
// indication of whether or not the object needs a finalization
// callback, and a function pointer used to finalize the object when
// the garbage collector determines that the object is no longer
// reachable. There is a GCInfo struct for each class that directly
// inherits from GarbageCollected or GarbageCollectedFinalized.
struct GCInfo {
bool hasFinalizer() const { return m_nonTrivialFinalizer; }
bool hasVTable() const { return m_hasVTable; }
TraceCallback m_trace;
FinalizationCallback m_finalize;
bool m_nonTrivialFinalizer;
bool m_hasVTable;
#if ENABLE(GC_PROFILING)
// |m_className| is held as a reference to prevent dtor being called at exit.
const String& m_className;
#endif
};
// The FinalizerTraitImpl specifies how to finalize objects. Object
// that inherit from GarbageCollectedFinalized are finalized by
// calling their 'finalize' method which by default will call the
// destructor on the object.
template<typename T, bool isGarbageCollectedFinalized>
struct FinalizerTraitImpl;
template<typename T>
struct FinalizerTraitImpl<T, true> {
static void finalize(void* obj) { static_cast<T*>(obj)->finalizeGarbageCollectedObject(); };
};
template<typename T>
struct FinalizerTraitImpl<T, false> {
static void finalize(void* obj) { };
};
// The FinalizerTrait is used to determine if a type requires
// finalization and what finalization means.
//
// By default classes that inherit from GarbageCollectedFinalized need
// finalization and finalization means calling the 'finalize' method
// of the object. The FinalizerTrait can be specialized if the default
// behavior is not desired.
template<typename T>
struct FinalizerTrait {
static const bool nonTrivialFinalizer = WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<T>::Type, GarbageCollectedFinalized>::value;
static void finalize(void* obj) { FinalizerTraitImpl<T, nonTrivialFinalizer>::finalize(obj); }
};
// Trait to get the GCInfo structure for types that have their
// instances allocated in the Blink garbage-collected heap.
template<typename T> struct GCInfoTrait;
template<typename T> class GarbageCollected;
class GarbageCollectedMixin;
template<typename T, bool = WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<T>::Type, GarbageCollected>::value> class NeedsAdjustAndMark;
template<typename T>
class NeedsAdjustAndMark<T, true> {
public:
static const bool value = false;
};
template <typename T> const bool NeedsAdjustAndMark<T, true>::value;
template<typename T>
class NeedsAdjustAndMark<T, false> {
public:
static const bool value = WTF::IsSubclass<typename WTF::RemoveConst<T>::Type, GarbageCollectedMixin>::value;
};
template <typename T> const bool NeedsAdjustAndMark<T, false>::value;
template<typename T, bool = NeedsAdjustAndMark<T>::value> class DefaultTraceTrait;
// The TraceTrait is used to specify how to mark an object pointer and
// how to trace all of the pointers in the object.
//
// By default, the 'trace' method implemented on an object itself is
// used to trace the pointers to other heap objects inside the object.
//
// However, the TraceTrait can be specialized to use a different
// implementation. A common case where a TraceTrait specialization is
// needed is when multiple inheritance leads to pointers that are not
// to the start of the object in the Blink garbage-collected heap. In
// that case the pointer has to be adjusted before marking.
template<typename T>
class TraceTrait {
public:
// Default implementation of TraceTrait<T>::trace just statically
// dispatches to the trace method of the class T.
static void trace(Visitor* visitor, void* self)
{
}
static void mark(Visitor* visitor, const T* t)
{
}
};
template<typename T> class TraceTrait<const T> : public TraceTrait<T> { };
template<typename Collection>
struct OffHeapCollectionTraceTrait;
template<typename T>
struct ObjectAliveTrait {
static bool isAlive(Visitor*, T*);
};
// Visitor is used to traverse the Blink object graph. Used for the
// marking phase of the mark-sweep garbage collector.
//
// Pointers are marked and pushed on the marking stack by calling the
// |mark| method with the pointer as an argument.
//
// Pointers within objects are traced by calling the |trace| methods
// with the object as an argument. Tracing objects will mark all of the
// contained pointers and push them on the marking stack.
class PLATFORM_EXPORT Visitor {
public:
virtual ~Visitor() { }
template<typename T>
static void verifyGarbageCollectedIfMember(T*)
{
}
template<typename T>
static void verifyGarbageCollectedIfMember(Member<T>* t)
{
}
// One-argument templated mark method. This uses the static type of
// the argument to get the TraceTrait. By default, the mark method
// of the TraceTrait just calls the virtual two-argument mark method on this
// visitor, where the second argument is the static trace method of the trait.
template<typename T>
void mark(T* t)
{
}
// Member version of the one-argument templated trace method.
template<typename T>
void trace(const Member<T>& t)
{
}
// Fallback method used only when we need to trace raw pointers of T.
// This is the case when a member is a union where we do not support members.
template<typename T>
void trace(const T* t)
{
}
template<typename T>
void trace(T* t)
{
}
// WeakMember version of the templated trace method. It doesn't keep
// the traced thing alive, but will write null to the WeakMember later
// if the pointed-to object is dead. It's lying for this to be const,
// but the overloading resolver prioritizes constness too high when
// picking the correct overload, so all these trace methods have to have
// the same constness on their argument to allow the type to decide.
template<typename T>
void trace(const WeakMember<T>& t)
{
}
template<typename T>
void traceInCollection(T& t, WTF::ShouldWeakPointersBeMarkedStrongly strongify)
{
}
// Fallback trace method for part objects to allow individual trace methods
// to trace through a part object with visitor->trace(m_partObject). This
// takes a const argument, because otherwise it will match too eagerly: a
// non-const argument would match a non-const Vector<T>& argument better
// than the specialization that takes const Vector<T>&. For a similar reason,
// the other specializations take a const argument even though they are
// usually used with non-const arguments, otherwise this function would match
// too well.
template<typename T>
void trace(const T& t)
{
}
// The following trace methods are for off-heap collections.
template<typename T, size_t inlineCapacity>
void trace(const Vector<T, inlineCapacity>& vector)
{
}
template<typename T, size_t N>
void trace(const Deque<T, N>& deque)
{
}
#if !ENABLE(OILPAN)
// These trace methods are needed to allow compiling and calling trace on
// transition types. We need to support calls in the non-oilpan build
// because a fully transitioned type (which will have its trace method
// called) might trace a field that is in transition. Once transition types
// are removed these can be removed.
template<typename T> void trace(const OwnPtr<T>&) { }
template<typename T> void trace(const RefPtr<T>&) { }
template<typename T> void trace(const RawPtr<T>&) { }
template<typename T> void trace(const WeakPtr<T>&) { }
#endif
// This method marks an object and adds it to the set of objects
// that should have their trace method called. Since not all
// objects have vtables we have to have the callback as an
// explicit argument, but we can use the templated one-argument
// mark method above to automatically provide the callback
// function.
virtual void mark(const void*, TraceCallback) = 0;
virtual void markNoTracing(const void* pointer) { mark(pointer, reinterpret_cast<TraceCallback>(0)); }
virtual void markNoTracing(HeapObjectHeader* header) { mark(header, reinterpret_cast<TraceCallback>(0)); }
virtual void markNoTracing(FinalizedHeapObjectHeader* header) { mark(header, reinterpret_cast<TraceCallback>(0)); }
// Used to mark objects during conservative scanning.
virtual void mark(HeapObjectHeader*, TraceCallback) = 0;
virtual void mark(FinalizedHeapObjectHeader*, TraceCallback) = 0;
// Used to delay the marking of objects until the usual marking
// including emphemeron iteration is done. This is used to delay
// the marking of collection backing stores until we know if they
// are reachable from locations other than the collection front
// object. If collection backings are reachable from other
// locations we strongify them to avoid issues with iterators and
// weak processing.
virtual void registerDelayedMarkNoTracing(const void*) = 0;
// If the object calls this during the regular trace callback, then the
// WeakPointerCallback argument may be called later, when the strong roots
// have all been found. The WeakPointerCallback will normally use isAlive
// to find out whether some pointers are pointing to dying objects. When
// the WeakPointerCallback is done the object must have purged all pointers
// to objects where isAlive returned false. In the weak callback it is not
// allowed to touch other objects (except using isAlive) or to allocate on
// the GC heap. Note that even removing things from HeapHashSet or
// HeapHashMap can cause an allocation if the backing store resizes, but
// these collections know to remove WeakMember elements safely.
//
// The weak pointer callbacks are run on the thread that owns the
// object and other threads are not stopped during the
// callbacks. Since isAlive is used in the callback to determine
// if objects pointed to are alive it is crucial that the object
// pointed to belong to the same thread as the object receiving
// the weak callback. Since other threads have been resumed the
// mark bits are not valid for objects from other threads.
virtual void registerWeakMembers(const void* object, WeakPointerCallback callback) { registerWeakMembers(object, object, callback); }
virtual void registerWeakMembers(const void*, const void*, WeakPointerCallback) = 0;
template<typename T, void (T::*method)(Visitor*)>
void registerWeakMembers(const T* obj)
{
registerWeakMembers(obj, &TraceMethodDelegate<T, method>::trampoline);
}
// For simple cases where you just want to zero out a cell when the thing
// it is pointing at is garbage, you can use this. This will register a
// callback for each cell that needs to be zeroed, so if you have a lot of
// weak cells in your object you should still consider using
// registerWeakMembers above.
//
// In contrast to registerWeakMembers, the weak cell callbacks are
// run on the thread performing garbage collection. Therefore, all
// threads are stopped during weak cell callbacks.
template<typename T>
void registerWeakCell(T** cell)
{
registerWeakCell(reinterpret_cast<void**>(cell), &handleWeakCell<T>);
}
virtual void registerWeakTable(const void*, EphemeronCallback, EphemeronCallback) = 0;
#if ENABLE(ASSERT)
virtual bool weakTableRegistered(const void*) = 0;
#endif
virtual bool isMarked(const void*) = 0;
template<typename T> inline bool isAlive(T* obj)
{
// Check that we actually know the definition of T when tracing.
COMPILE_ASSERT(sizeof(T), WeNeedToKnowTheDefinitionOfTheTypeWeAreTracing);
// The strongification of collections relies on the fact that once a
// collection has been strongified, there is no way that it can contain
// non-live entries, so no entries will be removed. Since you can't set
// the mark bit on a null pointer, that means that null pointers are
// always 'alive'.
if (!obj)
return true;
return ObjectAliveTrait<T>::isAlive(this, obj);
}
template<typename T> inline bool isAlive(const Member<T>& member)
{
return isAlive(member.get());
}
template<typename T> inline bool isAlive(RawPtr<T> ptr)
{
return isAlive(ptr.get());
}
// Macro to declare methods needed for each typed heap.
#define DECLARE_VISITOR_METHODS(Type) \
virtual void mark(const Type*, TraceCallback) = 0; \
virtual bool isMarked(const Type*) = 0;
FOR_EACH_TYPED_HEAP(DECLARE_VISITOR_METHODS)
#undef DECLARE_VISITOR_METHODS
#if ENABLE(GC_PROFILE_MARKING)
void setHostInfo(void* object, const String& name)
{
m_hostObject = object;
m_hostName = name;
}
#endif
protected:
virtual void registerWeakCell(void**, WeakPointerCallback) = 0;
#if ENABLE(GC_PROFILE_MARKING)
void* m_hostObject;
String m_hostName;
#endif
private:
template<typename T>
static void handleWeakCell(Visitor* self, void* obj)
{
T** cell = reinterpret_cast<T**>(obj);
if (*cell && !self->isAlive(*cell))
*cell = 0;
}
};
// We trace vectors by using the trace trait on each element, which means you
// can have vectors of general objects (not just pointers to objects) that can
// be traced.
template<typename T, size_t N>
struct OffHeapCollectionTraceTrait<WTF::Vector<T, N, WTF::DefaultAllocator> > {
typedef WTF::Vector<T, N, WTF::DefaultAllocator> Vector;
static void trace(Visitor* visitor, const Vector& vector)
{
}
};
template<typename T, size_t N>
struct OffHeapCollectionTraceTrait<WTF::Deque<T, N> > {
typedef WTF::Deque<T, N> Deque;
static void trace(Visitor* visitor, const Deque& deque)
{
}
};
template<typename T, typename Traits = WTF::VectorTraits<T> >
class HeapVectorBacking;
template<typename Table>
class HeapHashTableBacking {
public:
static void finalize(void* pointer);
};
template<typename T>
class DefaultTraceTrait<T, false> {
public:
static void mark(Visitor* visitor, const T* t)
{
}
};
template<typename T>
class DefaultTraceTrait<T, true> {
public:
static void mark(Visitor* visitor, const T* self)
{
if (!self)
return;
// Before doing adjustAndMark we need to check if the page is orphaned
// since we cannot call adjustAndMark if so, as there will be no vtable.
// If orphaned just mark the page as traced.
BaseHeapPage* heapPage = pageHeaderFromObject(self);
if (heapPage->orphaned()) {
heapPage->setTracedAfterOrphaned();
return;
}
self->adjustAndMark(visitor);
}
};
template<typename T, bool = NeedsAdjustAndMark<T>::value> class DefaultObjectAliveTrait;
template<typename T>
class DefaultObjectAliveTrait<T, false> {
public:
static bool isAlive(Visitor* visitor, T* obj)
{
return visitor->isMarked(obj);
}
};
template<typename T>
class DefaultObjectAliveTrait<T, true> {
public:
static bool isAlive(Visitor* visitor, T* obj)
{
return obj->isAlive(visitor);
}
};
template<typename T> bool ObjectAliveTrait<T>::isAlive(Visitor* visitor, T* obj)
{
return DefaultObjectAliveTrait<T>::isAlive(visitor, obj);
}
// The GarbageCollectedMixin interface and helper macro
// USING_GARBAGE_COLLECTED_MIXIN can be used to automatically define
// TraceTrait/ObjectAliveTrait on non-leftmost deriving classes
// which need to be garbage collected.
//
// Consider the following case:
// class B {};
// class A : public GarbageCollected, public B {};
//
// We can't correctly handle "Member<B> p = &a" as we can't compute addr of
// object header statically. This can be solved by using GarbageCollectedMixin:
// class B : public GarbageCollectedMixin {};
// class A : public GarbageCollected, public B {
// USING_GARBAGE_COLLECTED_MIXIN(A)
// };
//
// With the helper, as long as we are using Member<B>, TypeTrait<B> will
// dispatch adjustAndMark dynamically to find collect addr of the object header.
// Note that this is only enabled for Member<B>. For Member<A> which we can
// compute the object header addr statically, this dynamic dispatch is not used.
class PLATFORM_EXPORT GarbageCollectedMixin {
public:
virtual void adjustAndMark(Visitor*) const { };
virtual bool isAlive(Visitor*) const { return true; };
virtual void trace(Visitor*) { }
};
#define USING_GARBAGE_COLLECTED_MIXIN(TYPE) \
public: \
virtual void adjustAndMark(blink::Visitor* visitor) const override \
{ \
typedef WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<TYPE>::Type, blink::GarbageCollected> IsSubclassOfGarbageCollected; \
COMPILE_ASSERT(IsSubclassOfGarbageCollected::value, OnlyGarbageCollectedObjectsCanHaveGarbageCollectedMixins); \
visitor->mark(static_cast<const TYPE*>(this), &blink::TraceTrait<TYPE>::trace); \
} \
virtual bool isAlive(blink::Visitor* visitor) const override \
{ \
return visitor->isAlive(this); \
} \
private:
#if ENABLE(OILPAN)
#define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TYPE) USING_GARBAGE_COLLECTED_MIXIN(TYPE)
#else
#define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TYPE)
#endif
#if ENABLE(GC_PROFILING)
template<typename T>
struct TypenameStringTrait {
static const String& get()
{
DEFINE_STATIC_LOCAL(String, typenameString, (WTF::extractTypeNameFromFunctionName(WTF::extractNameFunction<T>())));
return typenameString;
}
};
#endif
template<typename T>
struct GCInfoAtBase {
static const GCInfo* get()
{
static const GCInfo gcInfo = {
TraceTrait<T>::trace,
FinalizerTrait<T>::finalize,
FinalizerTrait<T>::nonTrivialFinalizer,
WTF::IsPolymorphic<T>::value,
#if ENABLE(GC_PROFILING)
TypenameStringTrait<T>::get()
#endif
};
return &gcInfo;
}
};
template<typename T> class GarbageCollected;
template<typename T, bool = WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<T>::Type, GarbageCollected>::value> struct GetGarbageCollectedBase;
template<typename T>
struct GetGarbageCollectedBase<T, true> {
typedef typename T::GarbageCollectedBase type;
};
template<typename T>
struct GetGarbageCollectedBase<T, false> {
typedef T type;
};
template<typename T>
struct GCInfoTrait {
static const GCInfo* get()
{
return GCInfoAtBase<typename GetGarbageCollectedBase<T>::type>::get();
}
};
}
#endif

View File

@ -1,77 +0,0 @@
/*
* Copyright (C) 2013 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* typedef void (*PushAllRegistersCallback)(SafePointBarrier*, ThreadState*, intptr_t*);
* extern "C" void pushAllRegisters(SafePointBarrier*, ThreadState*, PushAllRegistersCallback)
*/
.type pushAllRegisters, %function
.global pushAllRegisters
.hidden pushAllRegisters
#ifdef __thumb__
/* In THUMB Mode jump to ARM stub via bx to ensure CPU mode switch.
* FIXME: This trampoline is provided to workaround bugs in
* the THUMB/ARM interworking that appear in the component build.
* When these issues are resolved this stub can be removed.
*/
.align 2
.code 16
.thumb_func
pushAllRegisters:
adr r3, pushAllRegistersARM
bx r3
.type pushAllRegistersARM, %function
.hidden pushAllRegistersARM
.align 4
.code 32
pushAllRegistersARM:
#else
/* ARM Mode */
.align 4
.code 32
pushAllRegisters:
#endif
/* Push all callee-saved registers and save return address. */
push {r4-r11, lr}
/* Pass the two first arguments unchanged (r0, r1)
* and pass the stack pointer after pushing callee-saved
* registers to the callback function.
*/
mov r3, r2
mov r2, sp
blx r3
/* Discard all the registers, and pop lr into pc which returns
* and switches mode if needed.
*/
add sp, sp, #32
pop {pc}

View File

@ -1,62 +0,0 @@
/*
* Copyright (C) 2014 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* typedef void (*PushAllRegistersCallback)(SafePointBarrier*, ThreadState*, intptr_t*);
* extern "C" void pushAllRegisters(SafePointBarrier*, ThreadState*, PushAllRegistersCallback)
*/
.type pushAllRegisters, %function
.global pushAllRegisters
.hidden pushAllRegisters
pushAllRegisters:
/* Save return address. */
sub sp, sp, #96
stp x19, x20, [sp, #80]
stp x21, x22, [sp, #64]
stp x23, x24, [sp, #48]
stp x25, x26, [sp, #32]
stp x27, x28, [sp, #16]
stp x30, x29, [sp, #0] // x30 is lr.
/* Pass the two first arguments unchanged (x0, x1)
* and pass the stack pointer as third argument to the
* callback function.
*/
mov x3, x2
mov x2, sp
blr x3
/* We don't restore all registers since they are callee saved (so
* the callback didn't clobber them) and we didn't modify them either.
*/
ldr x30, [sp], #96
ret

View File

@ -1,64 +0,0 @@
/*
* Copyright (C) 2013 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* typedef void (*PushAllRegistersCallback)(SafePointBarrier*, ThreadState*, intptr_t*);
* extern "C" void pushAllRegisters(SafePointBarrier*, ThreadState*, PushAllRegistersCallback)
*/
.type pushAllRegisters, %function
.global pushAllRegisters
.hidden pushAllRegisters
pushAllRegisters:
// Reserve space for callee-saved registers, return address,
// as well as for the callee arguments.
addiu $sp,$sp,-56
// Save the callee-saved registers and the return address.
sw $s0,16($sp)
sw $s1,20($sp)
sw $s2,24($sp)
sw $s3,28($sp)
sw $s4,32($sp)
sw $s5,36($sp)
sw $s6,40($sp)
sw $s7,44($sp)
sw $ra,48($sp)
// Pass the two first arguments untouched in a0 and a1 and the
// stack pointer to the callback.
move $t9,$a2
move $a2,$sp
jal $t9
// Restore return address, adjust stack and return. No
// callee-saved register was changed so we do not have to
// restore callee-saved registers.
lw $ra,48($sp)
addiu $sp,$sp,56
jr $ra

View File

@ -1,41 +0,0 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/*
* typedef void (*PushAllRegistersCallback)(SafePointBarrier*, ThreadState*, intptr_t*);
* extern "C" void pushAllRegisters(SafePointBarrier*, ThreadState*, PushAllRegistersCallback)
*/
.type pushAllRegisters, %function
.global pushAllRegisters
.hidden pushAllRegisters
pushAllRegisters:
// Push all callee-saves registers to get them
// on the stack for conservative stack scanning.
// Reserve space for callee-saved registers and return address.
daddiu $sp,$sp,-80
// Save the callee-saved registers and the return address.
sd $s0,0($sp)
sd $s1,8($sp)
sd $s2,16($sp)
sd $s3,24($sp)
sd $s4,32($sp)
sd $s5,40($sp)
sd $s6,48($sp)
sd $s7,56($sp)
sd $ra,64($sp)
// Note: the callee-saved floating point registers do not need to be
// copied to the stack, because fp registers never hold heap pointers
// and so do not need to be kept visible to the garbage collector.
// Pass the two first arguments untouched in a0 and a1 and the
// stack pointer to the callback.
move $t9,$a2
move $a2,$sp
jal $t9
// Restore return address, adjust stack and return.
// Note: the copied registers do not need to be reloaded here,
// because they were preserved by the called routine.
ld $ra,64($sp)
daddiu $sp,$sp,80
jr $ra

View File

@ -1,155 +0,0 @@
;; Copyright (C) 2013 Google Inc. All rights reserved.
;;
;; Redistribution and use in source and binary forms, with or without
;; modification, are permitted provided that the following conditions are
;; met:
;;
;; * Redistributions of source code must retain the above copyright
;; notice, this list of conditions and the following disclaimer.
;; * Redistributions in binary form must reproduce the above
;; copyright notice, this list of conditions and the following disclaimer
;; in the documentation and/or other materials provided with the
;; distribution.
;; * Neither the name of Google Inc. nor the names of its
;; contributors may be used to endorse or promote products derived from
;; this software without specific prior written permission.
;;
;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
;; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
;; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
;; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;;
%ifndef X64POSIX
%define X64POSIX 0
%endif
%ifndef X64WIN
%define X64WIN 0
%endif
%ifndef IA32
%define IA32 0
%endif
%ifndef ARM
%define ARM 0
%endif
;; Prefix symbols by '_' if PREFIX is defined.
%ifdef PREFIX
%define mangle(x) _ %+ x
%else
%define mangle(x) x
%endif
; PRIVATE makes a symbol private.
%ifidn __OUTPUT_FORMAT__,elf32
%define PRIVATE :hidden
%elifidn __OUTPUT_FORMAT__,elf64
%define PRIVATE :hidden
%elifidn __OUTPUT_FORMAT__,elfx32
%define PRIVATE :hidden
%elif X64WIN
%define PRIVATE
%else
%define PRIVATE :private_extern
%endif
;; typedef void (*PushAllRegistersCallback)(SafePointBarrier*, ThreadState*, intptr_t*);
;; extern "C" void pushAllRegisters(SafePointBarrier*, ThreadState*, PushAllRegistersCallback)
global mangle(pushAllRegisters) PRIVATE
%if X64POSIX
mangle(pushAllRegisters):
;; Push all callee-saves registers to get them
;; on the stack for conservative stack scanning.
;; We maintain 16-byte alignment at calls (required on Mac).
;; There is an 8-byte return address on the stack and we push
;; 56 bytes which maintains 16-byte stack alignment
;; at the call.
push 0
push rbx
push rbp
push r12
push r13
push r14
push r15
;; Pass the two first arguments unchanged (rdi, rsi)
;; and the stack pointer after pushing callee-saved
;; registers to the callback.
mov r8, rdx
mov rdx, rsp
call r8
;; Pop the callee-saved registers. None of them were
;; modified so no restoring is needed.
add rsp, 56
ret
%elif X64WIN
mangle(pushAllRegisters):
;; Push all callee-saves registers to get them
;; on the stack for conservative stack scanning.
push rsi
push rdi
push rbx
push rbp
push r12
push r13
push r14
push r15
;; Pass the two first arguments unchanged (rcx, rdx)
;; and the stack pointer after pushing callee-saved
;; registers to the callback.
mov r9, r8
mov r8, rsp
call r9
;; Pop the callee-saved registers. None of them were
;; modified so no restoring is needed.
add rsp, 64
ret
%elif IA32
mangle(pushAllRegisters):
;; Push all callee-saves registers to get them
;; on the stack for conservative stack scanning.
;; We maintain 16-byte alignment at calls (required on
;; Mac). There is a 4-byte return address on the stack
;; and we push 28 bytes which maintains 16-byte alignment
;; at the call.
push ebx
push ebp
push esi
push edi
;; Pass the two first arguments unchanged and the
;; stack pointer after pushing callee-save registers
;; to the callback.
mov ecx, [esp + 28]
push esp
push dword [esp + 28]
push dword [esp + 28]
call ecx
;; Pop arguments and the callee-saved registers.
;; None of the callee-saved registers were modified
;; so we do not need to restore them.
add esp, 28
ret
%elif ARM
%error "Yasm does not support arm. Use SaveRegisters_arm.S on arm."
%else
%error "Unsupported platform."
%endif

View File

@ -1,4 +0,0 @@
include_rules = [
"+heap",
"+public/platform",
]

View File

@ -1,73 +0,0 @@
/*
* Copyright (C) 2014 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PendingGCRunner_h
#define PendingGCRunner_h
#include "platform/heap/ThreadState.h"
#include "public/platform/WebThread.h"
namespace blink {
class PendingGCRunner : public blink::WebThread::TaskObserver {
public:
PendingGCRunner() : m_nesting(0) { }
~PendingGCRunner()
{
// m_nesting can be 1 if this was unregistered in a task and
// didProcessTask was not called.
ASSERT(!m_nesting || m_nesting == 1);
}
virtual void willProcessTask()
{
m_nesting++;
}
virtual void didProcessTask()
{
// In the production code WebKit::initialize is called from inside the
// message loop so we can get didProcessTask() without corresponding
// willProcessTask once. This is benign.
if (m_nesting)
m_nesting--;
blink::ThreadState* state = blink::ThreadState::current();
state->safePoint(m_nesting ? blink::ThreadState::HeapPointersOnStack : blink::ThreadState::NoHeapPointersOnStack);
}
private:
int m_nesting;
};
}
#endif

View File

@ -14,6 +14,7 @@
#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/GraphicsLayer.h"
#include "platform/graphics/gpu/Extensions3DUtil.h"
#include "platform/graphics/media/MediaPlayer.h"
#include "platform/graphics/skia/GaneshUtils.h"
#include "public/platform/Platform.h"
#include "public/platform/WebCString.h"

View File

@ -97,8 +97,6 @@ namespace WTF {
class HashTableConstIterator;
template<typename Value, typename HashFunctions, typename HashTraits, typename Allocator>
class LinkedHashSet;
template<WeakHandlingFlag x, typename T, typename U, typename V, typename W, typename X, typename Y, typename Z>
struct WeakProcessingHashTableHelper;
typedef enum { HashItemKnownGood } HashItemKnownGoodTag;
@ -563,7 +561,6 @@ namespace WTF {
mutable OwnPtr<Stats> m_stats;
#endif
template<WeakHandlingFlag x, typename T, typename U, typename V, typename W, typename X, typename Y, typename Z> friend struct WeakProcessingHashTableHelper;
template<typename T, typename U, typename V, typename W> friend class LinkedHashSet;
};
@ -1151,136 +1148,6 @@ namespace WTF {
return *this;
}
template<WeakHandlingFlag weakHandlingFlag, typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
struct WeakProcessingHashTableHelper;
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
struct WeakProcessingHashTableHelper<NoWeakHandlingInCollections, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> {
static void process(typename Allocator::Visitor* visitor, void* closure) { }
static void ephemeronIteration(typename Allocator::Visitor* visitor, void* closure) { }
static void ephemeronIterationDone(typename Allocator::Visitor* visitor, void* closure) { }
};
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
struct WeakProcessingHashTableHelper<WeakHandlingInCollections, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> {
// Used for purely weak and for weak-and-strong tables (ephemerons).
static void process(typename Allocator::Visitor* visitor, void* closure)
{
typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> HashTableType;
HashTableType* table = reinterpret_cast<HashTableType*>(closure);
if (table->m_table) {
// This is run as part of weak processing after full
// marking. The backing store is therefore marked if
// we get here.
ASSERT(visitor->isAlive(table->m_table));
// Now perform weak processing (this is a no-op if the backing
// was accessible through an iterator and was already marked
// strongly).
typedef typename HashTableType::ValueType ValueType;
for (ValueType* element = table->m_table + table->m_tableSize - 1; element >= table->m_table; element--) {
if (!HashTableType::isEmptyOrDeletedBucket(*element)) {
// At this stage calling trace can make no difference
// (everything is already traced), but we use the
// return value to remove things from the collection.
if (TraceInCollectionTrait<WeakHandlingInCollections, WeakPointersActWeak, ValueType, Traits>::trace(visitor, *element)) {
table->registerModification();
HashTableType::deleteBucket(*element); // Also calls the destructor.
table->m_deletedCount++;
table->m_keyCount--;
// We don't rehash the backing until the next add
// or delete, because that would cause allocation
// during GC.
}
}
}
}
}
// Called repeatedly for tables that have both weak and strong pointers.
static void ephemeronIteration(typename Allocator::Visitor* visitor, void* closure)
{
typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> HashTableType;
HashTableType* table = reinterpret_cast<HashTableType*>(closure);
if (table->m_table) {
// Check the hash table for elements that we now know will not
// be removed by weak processing. Those elements need to have
// their strong pointers traced.
typedef typename HashTableType::ValueType ValueType;
for (ValueType* element = table->m_table + table->m_tableSize - 1; element >= table->m_table; element--) {
if (!HashTableType::isEmptyOrDeletedBucket(*element))
TraceInCollectionTrait<WeakHandlingInCollections, WeakPointersActWeak, ValueType, Traits>::trace(visitor, *element);
}
}
}
// Called when the ephemeron iteration is done and before running the per thread
// weak processing. It is guaranteed to be called before any thread is resumed.
static void ephemeronIterationDone(typename Allocator::Visitor* visitor, void* closure)
{
typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> HashTableType;
HashTableType* table = reinterpret_cast<HashTableType*>(closure);
ASSERT(Allocator::weakTableRegistered(visitor, table));
table->clearEnqueued();
}
};
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::trace(typename Allocator::Visitor* visitor)
{
// If someone else already marked the backing and queued up the trace
// and/or weak callback then we are done. This optimization does not
// happen for ListHashSet since its iterator does not point at the
// backing.
if (!m_table || visitor->isAlive(m_table))
return;
// Normally, we mark the backing store without performing trace. This
// means it is marked live, but the pointers inside it are not marked.
// Instead we will mark the pointers below. However, for backing
// stores that contain weak pointers the handling is rather different.
// We don't mark the backing store here, so the marking GC will leave
// the backing unmarked. If the backing is found in any other way than
// through its HashTable (ie from an iterator) then the mark bit will
// be set and the pointers will be marked strongly, avoiding problems
// with iterating over things that disappear due to weak processing
// while we are iterating over them. We register the backing store
// pointer for delayed marking which will take place after we know if
// the backing is reachable from elsewhere. We also register a
// weakProcessing callback which will perform weak processing if needed.
if (Traits::weakHandlingFlag == NoWeakHandlingInCollections) {
Allocator::markNoTracing(visitor, m_table);
} else {
Allocator::registerDelayedMarkNoTracing(visitor, m_table);
Allocator::registerWeakMembers(visitor, this, m_table, WeakProcessingHashTableHelper<Traits::weakHandlingFlag, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::process);
}
if (ShouldBeTraced<Traits>::value) {
if (Traits::weakHandlingFlag == WeakHandlingInCollections) {
// If we have both strong and weak pointers in the collection
// then we queue up the collection for fixed point iteration a
// la Ephemerons:
// http://dl.acm.org/citation.cfm?doid=263698.263733 - see also
// http://www.jucs.org/jucs_14_21/eliminating_cycles_in_weak
ASSERT(!enqueued() || Allocator::weakTableRegistered(visitor, this));
if (!enqueued()) {
Allocator::registerWeakTable(visitor, this,
WeakProcessingHashTableHelper<Traits::weakHandlingFlag, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::ephemeronIteration,
WeakProcessingHashTableHelper<Traits::weakHandlingFlag, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::ephemeronIterationDone);
setEnqueued();
}
// We don't need to trace the elements here, since registering
// as a weak table above will cause them to be traced (perhaps
// several times). It's better to wait until everything else is
// traced before tracing the elements for the first time; this
// may reduce (by one) the number of iterations needed to get
// to a fixed point.
return;
}
for (ValueType* element = m_table + m_tableSize - 1; element >= m_table; element--) {
if (!isEmptyOrDeletedBucket(*element))
Allocator::template trace<ValueType, Traits>(visitor, *element);
}
}
}
// iterator adapters
template<typename HashTableType, typename Traits> struct HashTableConstIteratorAdapter {