• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "CheckFieldsVisitor.h"
6 
7 #include <cassert>
8 
9 #include "BlinkGCPluginOptions.h"
10 #include "RecordInfo.h"
11 
CheckFieldsVisitor()12 CheckFieldsVisitor::CheckFieldsVisitor()
13     : current_(0),
14       stack_allocated_host_(false) {
15 }
16 
invalid_fields()17 CheckFieldsVisitor::Errors& CheckFieldsVisitor::invalid_fields() {
18   return invalid_fields_;
19 }
20 
ContainsInvalidFields(RecordInfo * info)21 bool CheckFieldsVisitor::ContainsInvalidFields(RecordInfo* info) {
22   stack_allocated_host_ = info->IsStackAllocated();
23   managed_host_ = stack_allocated_host_ ||
24                   info->IsGCAllocated() ||
25                   info->IsNonNewable() ||
26                   info->IsOnlyPlacementNewable();
27   for (RecordInfo::Fields::iterator it = info->GetFields().begin();
28        it != info->GetFields().end();
29        ++it) {
30     context().clear();
31     current_ = &it->second;
32     current_->edge()->Accept(this);
33   }
34   return !invalid_fields_.empty();
35 }
36 
AtMember(Member * edge)37 void CheckFieldsVisitor::AtMember(Member* edge) {
38   if (managed_host_)
39     return;
40   // A member is allowed to appear in the context of a root.
41   for (Context::iterator it = context().begin();
42        it != context().end();
43        ++it) {
44     if ((*it)->Kind() == Edge::kRoot)
45       return;
46   }
47   invalid_fields_.push_back(std::make_pair(current_, kMemberInUnmanaged));
48 }
49 
AtIterator(Iterator * edge)50 void CheckFieldsVisitor::AtIterator(Iterator* edge) {
51   if (!managed_host_)
52     return;
53 
54   if (edge->IsUnsafe())
55     invalid_fields_.push_back(std::make_pair(current_, kIteratorToGCManaged));
56 }
57 
AtValue(Value * edge)58 void CheckFieldsVisitor::AtValue(Value* edge) {
59   // TODO: what should we do to check unions?
60   if (edge->value()->record()->isUnion())
61     return;
62 
63   if (!stack_allocated_host_ && edge->value()->IsStackAllocated()) {
64     invalid_fields_.push_back(std::make_pair(current_, kPtrFromHeapToStack));
65     return;
66   }
67 
68   if (!Parent() &&
69       edge->value()->IsGCDerived() &&
70       !edge->value()->IsGCMixin()) {
71     invalid_fields_.push_back(std::make_pair(current_, kGCDerivedPartObject));
72     return;
73   }
74 
75   // If in a stack allocated context, be fairly insistent that T in Member<T>
76   // is GC allocated, as stack allocated objects do not have a trace()
77   // that separately verifies the validity of Member<T>.
78   //
79   // Notice that an error is only reported if T's definition is in scope;
80   // we do not require that it must be brought into scope as that would
81   // prevent declarations of mutually dependent class types.
82   //
83   // (Note: Member<>'s constructor will at run-time verify that the
84   // pointer it wraps is indeed heap allocated.)
85   if (stack_allocated_host_ && Parent() && Parent()->IsMember() &&
86       edge->value()->HasDefinition() && !edge->value()->IsGCAllocated()) {
87     invalid_fields_.push_back(std::make_pair(current_,
88                                              kMemberToGCUnmanaged));
89     return;
90   }
91 
92   if (!Parent() || !edge->value()->IsGCAllocated())
93     return;
94 
95   // Disallow  OwnPtr<T>, RefPtr<T> and T* to stack-allocated types.
96   if (Parent()->IsOwnPtr() ||
97       Parent()->IsUniquePtr() ||
98       Parent()->IsRefPtr() ||
99       (stack_allocated_host_ && Parent()->IsRawPtr())) {
100     invalid_fields_.push_back(std::make_pair(
101         current_, InvalidSmartPtr(Parent())));
102     return;
103   }
104   if (Parent()->IsRawPtr()) {
105     RawPtr* rawPtr = static_cast<RawPtr*>(Parent());
106     Error error = rawPtr->HasReferenceType() ?
107         kReferencePtrToGCManaged : kRawPtrToGCManaged;
108     invalid_fields_.push_back(std::make_pair(current_, error));
109   }
110 }
111 
AtCollection(Collection * edge)112 void CheckFieldsVisitor::AtCollection(Collection* edge) {
113   if (edge->on_heap() && Parent() && Parent()->IsOwnPtr())
114     invalid_fields_.push_back(std::make_pair(current_, kOwnPtrToGCManaged));
115   if (edge->on_heap() && Parent() && Parent()->IsUniquePtr())
116     invalid_fields_.push_back(std::make_pair(current_, kUniquePtrToGCManaged));
117 }
118 
InvalidSmartPtr(Edge * ptr)119 CheckFieldsVisitor::Error CheckFieldsVisitor::InvalidSmartPtr(Edge* ptr) {
120   if (ptr->IsRawPtr()) {
121     if (static_cast<RawPtr*>(ptr)->HasReferenceType())
122       return kReferencePtrToGCManaged;
123     else
124       return kRawPtrToGCManaged;
125   }
126   if (ptr->IsRefPtr())
127     return kRefPtrToGCManaged;
128   if (ptr->IsOwnPtr())
129     return kOwnPtrToGCManaged;
130   if (ptr->IsUniquePtr())
131     return kUniquePtrToGCManaged;
132   assert(false && "Unknown smart pointer kind");
133 }
134