Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ppapi/proxy/raw_var_data.h" | 5 #include "ppapi/proxy/raw_var_data.h" |
| 6 | 6 |
| 7 #include <stack> | 7 #include <stack> |
| 8 | 8 |
| 9 #include "base/hash_tables.h" | 9 #include "base/hash_tables.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 // memory instead of sending the data over IPC. Light testing suggests | 28 // memory instead of sending the data over IPC. Light testing suggests |
| 29 // shared memory is much faster for 256K and larger messages. | 29 // shared memory is much faster for 256K and larger messages. |
| 30 static const uint32 kMinimumArrayBufferSizeForShmem = 256 * 1024; | 30 static const uint32 kMinimumArrayBufferSizeForShmem = 256 * 1024; |
| 31 static uint32 g_minimum_array_buffer_size_for_shmem = | 31 static uint32 g_minimum_array_buffer_size_for_shmem = |
| 32 kMinimumArrayBufferSizeForShmem; | 32 kMinimumArrayBufferSizeForShmem; |
| 33 | 33 |
| 34 void DefaultHandleWriter(IPC::Message* m, const SerializedHandle& handle) { | 34 void DefaultHandleWriter(IPC::Message* m, const SerializedHandle& handle) { |
| 35 IPC::ParamTraits<SerializedHandle>::Write(m, handle); | 35 IPC::ParamTraits<SerializedHandle>::Write(m, handle); |
| 36 } | 36 } |
| 37 | 37 |
| 38 struct StackEntry { | |
| 39 StackEntry(PP_Var v, size_t i) : var(v), data_index(i), sentinel(false) {} | |
| 40 PP_Var var; | |
| 41 size_t data_index; | |
| 42 // Used to track parent nodes on the stack as traversing the graph. | |
|
dmichael (off chromium)
2013/06/04 16:59:10
nit: as->while
raymes
2013/06/04 19:36:06
Done.
| |
| 43 bool sentinel; | |
| 44 }; | |
| 45 | |
| 38 // For a given PP_Var, returns the RawVarData associated with it, or creates a | 46 // For a given PP_Var, returns the RawVarData associated with it, or creates a |
| 39 // new one if there is no existing one. The data is appended to |data| if it | 47 // new one if there is no existing one. The data is appended to |data| if it |
| 40 // is newly created. The index into |data| pointing to the result is returned. | 48 // is newly created. The index into |data| pointing to the result is returned. |
| 41 // |id_map| keeps track of RawVarDatas that have already been created. | 49 // |visited_map| keeps track of RawVarDatas that have already been created. |
| 42 size_t GetOrCreateRawVarData(const PP_Var& var, | 50 size_t GetOrCreateRawVarData(const PP_Var& var, |
| 43 base::hash_map<int64_t, size_t>* id_map, | 51 base::hash_map<int64_t, size_t>* visited_map, |
| 44 ScopedVector<RawVarData>* data) { | 52 ScopedVector<RawVarData>* data) { |
| 45 if (VarTracker::IsVarTypeRefcounted(var.type)) { | 53 if (VarTracker::IsVarTypeRefcounted(var.type)) { |
| 46 base::hash_map<int64_t, size_t>::iterator it = id_map->find( | 54 base::hash_map<int64_t, size_t>::iterator it = visited_map->find( |
| 47 var.value.as_id); | 55 var.value.as_id); |
| 48 if (it != id_map->end()) { | 56 if (it != visited_map->end()) { |
| 49 return it->second; | 57 return it->second; |
| 50 } else { | 58 } else { |
| 51 data->push_back(RawVarData::Create(var.type)); | 59 data->push_back(RawVarData::Create(var.type)); |
| 52 (*id_map)[var.value.as_id] = data->size() - 1; | 60 (*visited_map)[var.value.as_id] = data->size() - 1; |
| 53 } | 61 } |
| 54 } else { | 62 } else { |
| 55 data->push_back(RawVarData::Create(var.type)); | 63 data->push_back(RawVarData::Create(var.type)); |
| 56 } | 64 } |
| 57 return data->size() - 1; | 65 return data->size() - 1; |
| 58 } | 66 } |
| 59 | 67 |
| 60 } // namespace | 68 } // namespace |
| 61 | 69 |
| 62 // RawVarDataGraph ------------------------------------------------------------ | 70 // RawVarDataGraph ------------------------------------------------------------ |
| 63 RawVarDataGraph::RawVarDataGraph() { | 71 RawVarDataGraph::RawVarDataGraph() { |
| 64 } | 72 } |
| 65 | 73 |
| 66 RawVarDataGraph::~RawVarDataGraph() { | 74 RawVarDataGraph::~RawVarDataGraph() { |
| 67 } | 75 } |
| 68 | 76 |
| 69 // static | 77 // static |
| 70 scoped_ptr<RawVarDataGraph> RawVarDataGraph::Create(const PP_Var& var, | 78 scoped_ptr<RawVarDataGraph> RawVarDataGraph::Create(const PP_Var& var, |
| 71 PP_Instance instance) { | 79 PP_Instance instance, |
| 80 bool allow_cycles) { | |
| 72 scoped_ptr<RawVarDataGraph> graph(new RawVarDataGraph); | 81 scoped_ptr<RawVarDataGraph> graph(new RawVarDataGraph); |
| 73 // Map of |var.value.as_id| to a RawVarData index in RawVarDataGraph. | 82 // Map of |var.value.as_id| to a RawVarData index in RawVarDataGraph. |
| 74 base::hash_map<int64_t, size_t> id_map; | 83 base::hash_map<int64_t, size_t> visited_map; |
| 84 base::hash_set<int64_t> parent_ids; | |
| 75 | 85 |
| 76 std::stack<std::pair<PP_Var, size_t> > stack; | 86 std::stack<StackEntry> stack; |
| 77 stack.push(make_pair(var, GetOrCreateRawVarData(var, &id_map, | 87 stack.push(StackEntry(var, GetOrCreateRawVarData(var, &visited_map, |
| 78 &graph->data_))); | 88 &graph->data_))); |
| 79 | 89 |
| 80 // Traverse the PP_Var graph with DFS. | 90 // Traverse the PP_Var graph with DFS. |
| 81 while (!stack.empty()) { | 91 while (!stack.empty()) { |
| 82 PP_Var current_var = stack.top().first; | 92 PP_Var current_var = stack.top().var; |
| 83 RawVarData* current_var_data = graph->data_[stack.top().second]; | 93 RawVarData* current_var_data = graph->data_[stack.top().data_index]; |
| 84 stack.pop(); | |
| 85 | 94 |
| 86 // If the node is initialized, it means we have visited it. | 95 if (stack.top().sentinel) { |
| 87 if (current_var_data->initialized()) | 96 stack.pop(); |
| 97 if (::ppapi::VarTracker::IsVarTypeRefcounted(var.type)) | |
|
dmichael (off chromium)
2013/06/04 16:59:10
I don't understand why you're looking at the type
raymes
2013/06/04 19:36:06
Yes...good catch. Thanks
| |
| 98 parent_ids.erase(current_var.value.as_id); | |
| 88 continue; | 99 continue; |
| 100 } else { | |
| 101 stack.top().sentinel = true; | |
| 102 if (::ppapi::VarTracker::IsVarTypeRefcounted(var.type)) | |
| 103 parent_ids.insert(current_var.value.as_id); | |
| 104 } | |
| 105 | |
| 106 // If the node is initialized, it means we have visited it already. | |
| 107 if (current_var_data->initialized()) { | |
| 108 continue; | |
| 109 } | |
| 89 | 110 |
| 90 if (!current_var_data->Init(current_var, instance)) { | 111 if (!current_var_data->Init(current_var, instance)) { |
| 91 NOTREACHED(); | 112 NOTREACHED(); |
| 92 return scoped_ptr<RawVarDataGraph>(); | 113 return scoped_ptr<RawVarDataGraph>(); |
| 93 } | 114 } |
| 94 | 115 |
| 95 // Add child nodes to the stack. | 116 // Add child nodes to the stack. |
| 96 if (current_var.type == PP_VARTYPE_ARRAY) { | 117 if (current_var.type == PP_VARTYPE_ARRAY) { |
| 97 ArrayVar* array_var = ArrayVar::FromPPVar(current_var); | 118 ArrayVar* array_var = ArrayVar::FromPPVar(current_var); |
| 98 if (!array_var) { | 119 if (!array_var) { |
| 99 NOTREACHED(); | 120 NOTREACHED(); |
| 100 return scoped_ptr<RawVarDataGraph>(); | 121 return scoped_ptr<RawVarDataGraph>(); |
| 101 } | 122 } |
| 102 for (ArrayVar::ElementVector::const_iterator iter = | 123 for (ArrayVar::ElementVector::const_iterator iter = |
| 103 array_var->elements().begin(); | 124 array_var->elements().begin(); |
| 104 iter != array_var->elements().end(); | 125 iter != array_var->elements().end(); |
| 105 ++iter) { | 126 ++iter) { |
| 106 size_t child_id = GetOrCreateRawVarData(iter->get(), &id_map, | 127 const PP_Var& child = iter->get(); |
| 128 if (!allow_cycles && | |
| 129 ::ppapi::VarTracker::IsVarTypeRefcounted(child.type) && | |
| 130 parent_ids.count(child.value.as_id) != 0) { | |
| 131 return scoped_ptr<RawVarDataGraph>(); | |
| 132 } | |
| 133 size_t child_id = GetOrCreateRawVarData(child, &visited_map, | |
| 107 &graph->data_); | 134 &graph->data_); |
| 108 static_cast<ArrayRawVarData*>(current_var_data)->AddChild(child_id); | 135 static_cast<ArrayRawVarData*>(current_var_data)->AddChild(child_id); |
| 109 stack.push(make_pair(iter->get(), child_id)); | 136 stack.push(StackEntry(child, child_id)); |
| 110 } | 137 } |
| 111 } else if (current_var.type == PP_VARTYPE_DICTIONARY) { | 138 } else if (current_var.type == PP_VARTYPE_DICTIONARY) { |
| 112 DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var); | 139 DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var); |
| 113 if (!dict_var) { | 140 if (!dict_var) { |
| 114 NOTREACHED(); | 141 NOTREACHED(); |
| 115 return scoped_ptr<RawVarDataGraph>(); | 142 return scoped_ptr<RawVarDataGraph>(); |
| 116 } | 143 } |
| 117 for (DictionaryVar::KeyValueMap::const_iterator iter = | 144 for (DictionaryVar::KeyValueMap::const_iterator iter = |
| 118 dict_var->key_value_map().begin(); | 145 dict_var->key_value_map().begin(); |
| 119 iter != dict_var->key_value_map().end(); | 146 iter != dict_var->key_value_map().end(); |
| 120 ++iter) { | 147 ++iter) { |
| 121 size_t child_id = GetOrCreateRawVarData(iter->second.get(), &id_map, | 148 const PP_Var& child = iter->second.get(); |
| 149 if (!allow_cycles && | |
| 150 ::ppapi::VarTracker::IsVarTypeRefcounted(child.type) && | |
| 151 parent_ids.count(child.value.as_id) != 0) { | |
| 152 return scoped_ptr<RawVarDataGraph>(); | |
| 153 } | |
| 154 size_t child_id = GetOrCreateRawVarData(child, &visited_map, | |
| 122 &graph->data_); | 155 &graph->data_); |
| 123 static_cast<DictionaryRawVarData*>( | 156 static_cast<DictionaryRawVarData*>( |
| 124 current_var_data)->AddChild(iter->first, child_id); | 157 current_var_data)->AddChild(iter->first, child_id); |
| 125 stack.push(make_pair(iter->second.get(), child_id)); | 158 stack.push(StackEntry(child, child_id)); |
| 126 } | 159 } |
| 127 } | 160 } |
| 128 } | 161 } |
| 129 return graph.Pass(); | 162 return graph.Pass(); |
| 130 } | 163 } |
| 131 | 164 |
| 132 PP_Var RawVarDataGraph::CreatePPVar(PP_Instance instance) { | 165 PP_Var RawVarDataGraph::CreatePPVar(PP_Instance instance) { |
| 133 // Create and initialize each node in the graph. | 166 // Create and initialize each node in the graph. |
| 134 std::vector<PP_Var> graph; | 167 std::vector<PP_Var> graph; |
| 135 for (size_t i = 0; i < data_.size(); ++i) | 168 for (size_t i = 0; i < data_.size(); ++i) |
| (...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 631 return false; | 664 return false; |
| 632 if (!m->ReadUInt32(iter, &value)) | 665 if (!m->ReadUInt32(iter, &value)) |
| 633 return false; | 666 return false; |
| 634 children_.push_back(make_pair(key, value)); | 667 children_.push_back(make_pair(key, value)); |
| 635 } | 668 } |
| 636 return true; | 669 return true; |
| 637 } | 670 } |
| 638 | 671 |
| 639 } // namespace proxy | 672 } // namespace proxy |
| 640 } // namespace ppapi | 673 } // namespace ppapi |
| OLD | NEW |