summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ppapi/proxy/host_var_serialization_rules.cc47
-rw-r--r--ppapi/proxy/host_var_serialization_rules.h12
-rw-r--r--ppapi/proxy/plugin_var_serialization_rules.cc27
-rw-r--r--ppapi/proxy/plugin_var_serialization_rules.h12
-rw-r--r--ppapi/proxy/ppp_messaging_proxy_perftest.cc20
-rw-r--r--ppapi/proxy/serialized_var.cc76
-rw-r--r--ppapi/proxy/serialized_var.h35
-rw-r--r--ppapi/proxy/serialized_var_unittest.cc2
-rw-r--r--ppapi/proxy/var_serialization_rules.h39
-rw-r--r--ppapi/shared_impl/var.cc18
-rw-r--r--ppapi/shared_impl/var.h9
11 files changed, 180 insertions, 117 deletions
diff --git a/ppapi/proxy/host_var_serialization_rules.cc b/ppapi/proxy/host_var_serialization_rules.cc
index 3f11090..45eaf40 100644
--- a/ppapi/proxy/host_var_serialization_rules.cc
+++ b/ppapi/proxy/host_var_serialization_rules.cc
@@ -24,19 +24,24 @@ HostVarSerializationRules::HostVarSerializationRules(PP_Module pp_module)
HostVarSerializationRules::~HostVarSerializationRules() {
}
-PP_Var HostVarSerializationRules::SendCallerOwned(const PP_Var& var,
- std::string* str_val) {
+PP_Var HostVarSerializationRules::SendCallerOwned(
+ const PP_Var& var,
+ const std::string** str_ptr_out) {
if (var.type == PP_VARTYPE_STRING)
- VarToString(var, str_val);
+ VarToStringPtr(var, str_ptr_out);
return var;
}
PP_Var HostVarSerializationRules::BeginReceiveCallerOwned(
const PP_Var& var,
- const std::string* str_val,
+ scoped_ptr<std::string> str,
Dispatcher* /* dispatcher */) {
- if (var.type == PP_VARTYPE_STRING)
- return StringVar::StringToPPVar(*str_val);
+ if (var.type == PP_VARTYPE_STRING) {
+ // Put the string in to the VarTracker (transferring ownership, since we
+ // would otherwise just delete the one we received from IPC). This allows
+ // us to avoid unnecessary copying of the string.
+ return StringVar::StringToPPVar(str.Pass());
+ }
return var;
}
@@ -47,12 +52,13 @@ void HostVarSerializationRules::EndReceiveCallerOwned(const PP_Var& var) {
}
}
-PP_Var HostVarSerializationRules::ReceivePassRef(const PP_Var& var,
- const std::string& str_val,
- Dispatcher* /* dispatcher */) {
+PP_Var HostVarSerializationRules::ReceivePassRef(
+ const PP_Var& var,
+ scoped_ptr<std::string> str,
+ Dispatcher* /* dispatcher */) {
if (var.type == PP_VARTYPE_STRING) {
- // Convert the string to the context of the current process.
- return StringVar::StringToPPVar(str_val);
+ // Put the string in to the tracker, transferring ownership.
+ return StringVar::StringToPPVar(str.Pass());
}
// See PluginVarSerialization::BeginSendPassRef for an example.
@@ -61,12 +67,13 @@ PP_Var HostVarSerializationRules::ReceivePassRef(const PP_Var& var,
return var;
}
-PP_Var HostVarSerializationRules::BeginSendPassRef(const PP_Var& var,
- std::string* str_val) {
+PP_Var HostVarSerializationRules::BeginSendPassRef(
+ const PP_Var& var,
+ const std::string** str_ptr_out) {
// See PluginVarSerialization::ReceivePassRef for an example. We don't need
// to do anything here other than convert the string.
if (var.type == PP_VARTYPE_STRING)
- VarToString(var, str_val);
+ VarToStringPtr(var, str_ptr_out);
return var;
}
@@ -76,16 +83,14 @@ void HostVarSerializationRules::EndSendPassRef(const PP_Var& /* var */,
// to do anything here.
}
-void HostVarSerializationRules::VarToString(const PP_Var& var,
- std::string* str) {
+void HostVarSerializationRules::VarToStringPtr(
+ const PP_Var& var,
+ const std::string** str_ptr_out) {
DCHECK(var.type == PP_VARTYPE_STRING);
-
- // This could be optimized to avoid an extra string copy by going to a lower
- // level of the browser's implementation of strings where we already have
- // a std::string.
+ *str_ptr_out = NULL;
StringVar* string_var = StringVar::FromPPVar(var);
if (string_var)
- *str = string_var->value();
+ *str_ptr_out = string_var->ptr();
}
void HostVarSerializationRules::ReleaseObjectRef(const PP_Var& var) {
diff --git a/ppapi/proxy/host_var_serialization_rules.h b/ppapi/proxy/host_var_serialization_rules.h
index bbbb3d7..609980f 100644
--- a/ppapi/proxy/host_var_serialization_rules.h
+++ b/ppapi/proxy/host_var_serialization_rules.h
@@ -22,22 +22,24 @@ class HostVarSerializationRules : public VarSerializationRules {
~HostVarSerializationRules();
// VarSerialization implementation.
- virtual PP_Var SendCallerOwned(const PP_Var& var, std::string* str_val);
+ virtual PP_Var SendCallerOwned(const PP_Var& var,
+ const std::string** str_ptr_out);
virtual PP_Var BeginReceiveCallerOwned(const PP_Var& var,
- const std::string* str_val,
+ scoped_ptr<std::string> str,
Dispatcher* dispatcher);
virtual void EndReceiveCallerOwned(const PP_Var& var);
virtual PP_Var ReceivePassRef(const PP_Var& var,
- const std::string& str_val,
+ scoped_ptr<std::string> str,
Dispatcher* dispatcher);
- virtual PP_Var BeginSendPassRef(const PP_Var& var, std::string* str_val);
+ virtual PP_Var BeginSendPassRef(const PP_Var& var,
+ const std::string** str_ptr_out);
virtual void EndSendPassRef(const PP_Var& var, Dispatcher* dispatcher);
virtual void ReleaseObjectRef(const PP_Var& var);
private:
// Converts the given var (which must be a VARTYPE_STRING) to the given
// string object.
- void VarToString(const PP_Var& var, std::string* str);
+ void VarToStringPtr(const PP_Var& var, const std::string** str);
PP_Module pp_module_;
diff --git a/ppapi/proxy/plugin_var_serialization_rules.cc b/ppapi/proxy/plugin_var_serialization_rules.cc
index 2e92dd5..87a3cc2 100644
--- a/ppapi/proxy/plugin_var_serialization_rules.cc
+++ b/ppapi/proxy/plugin_var_serialization_rules.cc
@@ -22,17 +22,19 @@ PluginVarSerializationRules::PluginVarSerializationRules()
PluginVarSerializationRules::~PluginVarSerializationRules() {
}
-PP_Var PluginVarSerializationRules::SendCallerOwned(const PP_Var& var,
- std::string* str_val) {
+PP_Var PluginVarSerializationRules::SendCallerOwned(
+ const PP_Var& var,
+ const std::string** str_ptr_out) {
// Objects need special translations to get the IDs valid in the host.
if (var.type == PP_VARTYPE_OBJECT)
return var_tracker_->GetHostObject(var);
- // Retrieve the string to use for IPC.
+ // Retrieve the pointer to the string in the tracker in order to send the
+ // string over IPC without unnecessary copies.
if (var.type == PP_VARTYPE_STRING) {
StringVar* string_var = StringVar::FromPPVar(var);
if (string_var)
- *str_val = string_var->value();
+ *str_ptr_out = string_var->ptr();
else
NOTREACHED() << "Trying to send unknown string over IPC.";
}
@@ -41,10 +43,10 @@ PP_Var PluginVarSerializationRules::SendCallerOwned(const PP_Var& var,
PP_Var PluginVarSerializationRules::BeginReceiveCallerOwned(
const PP_Var& var,
- const std::string* str_val,
+ scoped_ptr<std::string> str,
Dispatcher* dispatcher) {
if (var.type == PP_VARTYPE_STRING)
- return StringVar::StringToPPVar(*str_val);
+ return StringVar::StringToPPVar(str.Pass());
if (var.type == PP_VARTYPE_OBJECT) {
DCHECK(dispatcher->IsPlugin());
@@ -65,10 +67,10 @@ void PluginVarSerializationRules::EndReceiveCallerOwned(const PP_Var& var) {
}
PP_Var PluginVarSerializationRules::ReceivePassRef(const PP_Var& var,
- const std::string& str_val,
+ scoped_ptr<std::string> str,
Dispatcher* dispatcher) {
if (var.type == PP_VARTYPE_STRING)
- return StringVar::StringToPPVar(str_val);
+ return StringVar::StringToPPVar(str.Pass());
// Overview of sending an object with "pass ref" from the browser to the
// plugin:
@@ -96,8 +98,9 @@ PP_Var PluginVarSerializationRules::ReceivePassRef(const PP_Var& var,
return var;
}
-PP_Var PluginVarSerializationRules::BeginSendPassRef(const PP_Var& var,
- std::string* str_val) {
+PP_Var PluginVarSerializationRules::BeginSendPassRef(
+ const PP_Var& var,
+ const std::string** str_ptr_out) {
// Overview of sending an object with "pass ref" from the plugin to the
// browser:
// Example 1 Example 2
@@ -118,9 +121,11 @@ PP_Var PluginVarSerializationRules::BeginSendPassRef(const PP_Var& var,
return var_tracker_->GetHostObject(var);
if (var.type == PP_VARTYPE_STRING) {
+ // Get the pointer to the string that's in the tracker and return it, so we
+ // can avoid an extra copy of the string when serializing over IPC.
StringVar* string_var = StringVar::FromPPVar(var);
if (string_var)
- *str_val = string_var->value();
+ *str_ptr_out = string_var->ptr();
else
NOTREACHED() << "Trying to send unknown string over IPC.";
}
diff --git a/ppapi/proxy/plugin_var_serialization_rules.h b/ppapi/proxy/plugin_var_serialization_rules.h
index 6bd9638..8693505 100644
--- a/ppapi/proxy/plugin_var_serialization_rules.h
+++ b/ppapi/proxy/plugin_var_serialization_rules.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -22,15 +22,17 @@ class PluginVarSerializationRules : public VarSerializationRules {
~PluginVarSerializationRules();
// VarSerialization implementation.
- virtual PP_Var SendCallerOwned(const PP_Var& var, std::string* str_val);
+ virtual PP_Var SendCallerOwned(const PP_Var& var,
+ const std::string** str_ptr_out);
virtual PP_Var BeginReceiveCallerOwned(const PP_Var& var,
- const std::string* str_val,
+ scoped_ptr<std::string> str,
Dispatcher* dispatcher);
virtual void EndReceiveCallerOwned(const PP_Var& var);
virtual PP_Var ReceivePassRef(const PP_Var& var,
- const std::string& str_val,
+ scoped_ptr<std::string> str,
Dispatcher* dispatcher);
- virtual PP_Var BeginSendPassRef(const PP_Var& var, std::string* str_val);
+ virtual PP_Var BeginSendPassRef(const PP_Var& var,
+ const std::string** str_ptr_out);
virtual void EndSendPassRef(const PP_Var& var, Dispatcher* dispatcher);
virtual void ReleaseObjectRef(const PP_Var& var);
diff --git a/ppapi/proxy/ppp_messaging_proxy_perftest.cc b/ppapi/proxy/ppp_messaging_proxy_perftest.cc
index a58b025..ecdeb12 100644
--- a/ppapi/proxy/ppp_messaging_proxy_perftest.cc
+++ b/ppapi/proxy/ppp_messaging_proxy_perftest.cc
@@ -29,6 +29,7 @@ void HandleMessage(PP_Instance /* instance */, PP_Var message_data) {
// Do something simple with the string so the compiler won't complain.
if (s.length() > 0)
s[0] = 'a';
+ PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(message_data);
handle_message_called.Signal();
}
@@ -53,24 +54,29 @@ TEST_F(PppMessagingPerfTest, StringPerformance) {
host().host_dispatcher()->GetProxiedInterface(
PPP_MESSAGING_INTERFACE));
const PP_Instance kTestInstance = pp_instance();
- int string_size = 100000;
+ int seed = 123;
int string_count = 1000;
+ int max_string_size = 1000000;
CommandLine* command_line = CommandLine::ForCurrentProcess();
if (command_line) {
- if (command_line->HasSwitch("string_size")) {
- base::StringToInt(command_line->GetSwitchValueASCII("string_size"),
- &string_size);
+ if (command_line->HasSwitch("seed")) {
+ base::StringToInt(command_line->GetSwitchValueASCII("seed"),
+ &seed);
}
if (command_line->HasSwitch("string_count")) {
base::StringToInt(command_line->GetSwitchValueASCII("string_count"),
&string_count);
}
+ if (command_line->HasSwitch("max_string_size")) {
+ base::StringToInt(command_line->GetSwitchValueASCII("max_string_size"),
+ &max_string_size);
+ }
}
- // Make a string var of size string_size.
- const std::string kTestString(string_size, 'a');
+ srand(seed);
PerfTimeLogger logger("PppMessagingPerfTest.StringPerformance");
for (int i = 0; i < string_count; ++i) {
- PP_Var host_string = StringVar::StringToPPVar(kTestString);
+ const std::string test_string(rand() % max_string_size, 'a');
+ PP_Var host_string = StringVar::StringToPPVar(test_string);
ppp_messaging->HandleMessage(kTestInstance, host_string);
handle_message_called.Wait();
PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(host_string);
diff --git a/ppapi/proxy/serialized_var.cc b/ppapi/proxy/serialized_var.cc
index f9d59e5..00bb296 100644
--- a/ppapi/proxy/serialized_var.cc
+++ b/ppapi/proxy/serialized_var.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -19,6 +19,7 @@ namespace proxy {
SerializedVar::Inner::Inner()
: serialization_rules_(NULL),
var_(PP_MakeUndefined()),
+ tracker_string_ptr_(NULL),
cleanup_mode_(CLEANUP_NONE),
dispatcher_for_end_send_pass_ref_(NULL) {
#ifndef NDEBUG
@@ -30,18 +31,7 @@ SerializedVar::Inner::Inner()
SerializedVar::Inner::Inner(VarSerializationRules* serialization_rules)
: serialization_rules_(serialization_rules),
var_(PP_MakeUndefined()),
- cleanup_mode_(CLEANUP_NONE),
- dispatcher_for_end_send_pass_ref_(NULL) {
-#ifndef NDEBUG
- has_been_serialized_ = false;
- has_been_deserialized_ = false;
-#endif
-}
-
-SerializedVar::Inner::Inner(VarSerializationRules* serialization_rules,
- const PP_Var& var)
- : serialization_rules_(serialization_rules),
- var_(var),
+ tracker_string_ptr_(NULL),
cleanup_mode_(CLEANUP_NONE),
dispatcher_for_end_send_pass_ref_(NULL) {
#ifndef NDEBUG
@@ -86,14 +76,18 @@ void SerializedVar::Inner::SetVar(PP_Var var) {
var_ = var;
}
-const std::string& SerializedVar::Inner::GetString() const {
+scoped_ptr<std::string> SerializedVar::Inner::GetStringDestructive() {
DCHECK(serialization_rules_);
- return string_value_;
+ return string_from_ipc_.Pass();
}
-std::string* SerializedVar::Inner::GetStringPtr() {
+const std::string** SerializedVar::Inner::GetStringPtrPtr() {
DCHECK(serialization_rules_);
- return &string_value_;
+ // The caller will set our string pointer, and we promise not to change it.
+ // This path is taken for the "Send" side of SerializedVars, and we will only
+ // read the string in those cases, so it's safe for us to point directly to a
+ // string in the VarTracker.
+ return &tracker_string_ptr_;
}
void SerializedVar::Inner::ForceSetVarValueForTest(PP_Var value) {
@@ -101,7 +95,10 @@ void SerializedVar::Inner::ForceSetVarValueForTest(PP_Var value) {
}
void SerializedVar::Inner::ForceSetStringValueForTest(const std::string& str) {
- string_value_ = str;
+ // We don't need to change tracker_string_ptr_, as that is only used for
+ // serializing, and we're emulating a SerializedVar that was received from
+ // IPC.
+ string_from_ipc_.reset(new std::string(str));
}
void SerializedVar::Inner::WriteToMessage(IPC::Message* m) const {
@@ -126,7 +123,7 @@ void SerializedVar::Inner::WriteToMessage(IPC::Message* m) const {
// If the var is not a string type, we should not have ended up with any
// string data.
- DCHECK(var_.type == PP_VARTYPE_STRING || string_value_.empty());
+ DCHECK(var_.type == PP_VARTYPE_STRING || !tracker_string_ptr_);
m->WriteInt(static_cast<int>(var_.type));
switch (var_.type) {
@@ -150,7 +147,8 @@ void SerializedVar::Inner::WriteToMessage(IPC::Message* m) const {
// generated there. Then the function implementing the interface can
// handle the invalid string as if it was in process rather than seeing
// what looks like a valid empty string.
- m->WriteString(string_value_);
+ m->WriteString(tracker_string_ptr_ ? *tracker_string_ptr_
+ : std::string());
break;
case PP_VARTYPE_ARRAY_BUFFER:
// TODO(dmichael): Proxy ArrayBuffer.
@@ -207,7 +205,9 @@ bool SerializedVar::Inner::ReadFromMessage(const IPC::Message* m, void** iter) {
success = IPC::ParamTraits<double>::Read(m, iter, &var_.value.as_double);
break;
case PP_VARTYPE_STRING:
- success = m->ReadString(iter, &string_value_);
+ DCHECK(!tracker_string_ptr_ && !string_from_ipc_.get());
+ string_from_ipc_.reset(new std::string);
+ success = m->ReadString(iter, string_from_ipc_.get());
var_.value.as_id = 0;
break;
case PP_VARTYPE_OBJECT:
@@ -252,11 +252,6 @@ SerializedVar::SerializedVar(VarSerializationRules* serialization_rules)
: inner_(new Inner(serialization_rules)) {
}
-SerializedVar::SerializedVar(VarSerializationRules* serialization_rules,
- const PP_Var& var)
- : inner_(new Inner(serialization_rules, var)) {
-}
-
SerializedVar::~SerializedVar() {
}
@@ -266,7 +261,7 @@ SerializedVarSendInput::SerializedVarSendInput(Dispatcher* dispatcher,
const PP_Var& var)
: SerializedVar(dispatcher->serialization_rules()) {
inner_->SetVar(dispatcher->serialization_rules()->SendCallerOwned(
- var, inner_->GetStringPtr()));
+ var, inner_->GetStringPtrPtr()));
}
// static
@@ -274,13 +269,9 @@ void SerializedVarSendInput::ConvertVector(Dispatcher* dispatcher,
const PP_Var* input,
size_t input_count,
std::vector<SerializedVar>* output) {
- output->resize(input_count);
- for (size_t i = 0; i < input_count; i++) {
- SerializedVar& cur = (*output)[i];
- cur = SerializedVar(dispatcher->serialization_rules());
- cur.inner_->SetVar(dispatcher->serialization_rules()->SendCallerOwned(
- input[i], cur.inner_->GetStringPtr()));
- }
+ output->reserve(input_count);
+ for (size_t i = 0; i < input_count; i++)
+ output->push_back(SerializedVarSendInput(dispatcher, input[i]));
}
// ReceiveSerializedVarReturnValue ---------------------------------------------
@@ -296,7 +287,7 @@ ReceiveSerializedVarReturnValue::ReceiveSerializedVarReturnValue(
PP_Var ReceiveSerializedVarReturnValue::Return(Dispatcher* dispatcher) {
inner_->set_serialization_rules(dispatcher->serialization_rules());
inner_->SetVar(inner_->serialization_rules()->ReceivePassRef(
- inner_->GetIncompleteVar(), inner_->GetString(), dispatcher));
+ inner_->GetIncompleteVar(), inner_->GetStringDestructive(), dispatcher));
return inner_->GetVar();
}
@@ -313,8 +304,11 @@ ReceiveSerializedException::~ReceiveSerializedException() {
if (exception_) {
// When an output exception is specified, it will take ownership of the
// reference.
- inner_->SetVar(inner_->serialization_rules()->ReceivePassRef(
- inner_->GetIncompleteVar(), inner_->GetString(), dispatcher_));
+ inner_->SetVar(
+ inner_->serialization_rules()->ReceivePassRef(
+ inner_->GetIncompleteVar(),
+ inner_->GetStringDestructive(),
+ dispatcher_));
*exception_ = inner_->GetVar();
} else {
// When no output exception is specified, the browser thinks we have a ref
@@ -388,7 +382,7 @@ PP_Var SerializedVarReceiveInput::Get(Dispatcher* dispatcher) {
serialized_.inner_->SetVar(
serialized_.inner_->serialization_rules()->BeginReceiveCallerOwned(
serialized_.inner_->GetIncompleteVar(),
- serialized_.inner_->GetStringPtr(),
+ serialized_.inner_->GetStringDestructive(),
dispatcher));
return serialized_.inner_->GetVar();
}
@@ -419,7 +413,7 @@ PP_Var* SerializedVarVectorReceiveInput::Get(Dispatcher* dispatcher,
serialized_[i].inner_->SetVar(
serialized_[i].inner_->serialization_rules()->BeginReceiveCallerOwned(
serialized_[i].inner_->GetIncompleteVar(),
- serialized_[i].inner_->GetStringPtr(),
+ serialized_[i].inner_->GetStringDestructive(),
dispatcher));
deserialized_[i] = serialized_[i].inner_->GetVar();
}
@@ -445,7 +439,7 @@ void SerializedVarReturnValue::Return(Dispatcher* dispatcher,
serialized_->inner_->SetVar(
dispatcher->serialization_rules()->BeginSendPassRef(
var,
- serialized_->inner_->GetStringPtr()));
+ serialized_->inner_->GetStringPtrPtr()));
}
// static
@@ -472,7 +466,7 @@ SerializedVarOutParam::~SerializedVarOutParam() {
// in that case.
serialized_->inner_->SetVar(
serialized_->inner_->serialization_rules()->BeginSendPassRef(
- writable_var_, serialized_->inner_->GetStringPtr()));
+ writable_var_, serialized_->inner_->GetStringPtrPtr()));
// Normally the current object will be created on the stack to wrap a
// SerializedVar and won't have a scope around the actual IPC send. So we
diff --git a/ppapi/proxy/serialized_var.h b/ppapi/proxy/serialized_var.h
index c0cb1ac..1ad218d 100644
--- a/ppapi/proxy/serialized_var.h
+++ b/ppapi/proxy/serialized_var.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -10,6 +10,7 @@
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/proxy/ppapi_proxy_export.h"
@@ -87,7 +88,6 @@ class PPAPI_PROXY_EXPORT SerializedVar {
public:
Inner();
Inner(VarSerializationRules* serialization_rules);
- Inner(VarSerializationRules* serialization_rules, const PP_Var& var);
~Inner();
VarSerializationRules* serialization_rules() {
@@ -101,8 +101,14 @@ class PPAPI_PROXY_EXPORT SerializedVar {
PP_Var GetVar() const;
PP_Var GetIncompleteVar() const;
void SetVar(PP_Var var);
- const std::string& GetString() const;
- std::string* GetStringPtr();
+ void SetString(scoped_ptr<std::string> str);
+ // Return a new string with the contents of the string referenced by Inner.
+ // The string referenced by the Inner will be empty after this.
+ scoped_ptr<std::string> GetStringDestructive();
+ // Return a pointer to our internal string pointer. This is so that the
+ // caller will be able to make this Inner point to a string that's owned
+ // elsewhere (i.e., in the tracker).
+ const std::string** GetStringPtrPtr();
// For the SerializedVarTestConstructor, this writes the Var value as if
// it was just received off the wire, without any serialization rules.
@@ -137,7 +143,7 @@ class PPAPI_PROXY_EXPORT SerializedVar {
VarSerializationRules* serialization_rules_;
// If this is set to VARTYPE_STRING and the 'value.id' is 0, then the
- // string_value_ contains the string. This means that the caller hasn't
+ // string_from_ipc_ holds the string. This means that the caller hasn't
// called Deserialize with a valid Dispatcher yet, which is how we can
// convert the serialized string value to a PP_Var string ID.
//
@@ -146,9 +152,17 @@ class PPAPI_PROXY_EXPORT SerializedVar {
// a string ID. Before this, the as_id will be 0 for VARTYPE_STRING.
PP_Var var_;
- // Holds the literal string value to/from IPC. This will be valid if the
- // var_ is VARTYPE_STRING.
- std::string string_value_;
+ // If valid, this is a pointer to a string owned by the VarTracker. When our
+ // outer SerializedVar gets serialized, it will write the string directly
+ // from the tracker so we do not need to make any unnecessary copies. This
+ // should only be valid on the sender side.
+ const std::string* tracker_string_ptr_;
+
+ // If valid, this is a string received from IPC which needs to be inserted
+ // in to the var tracker. When we provide it to the tracker, we pass
+ // ownership so that there are no unnecessary copies. This should only ever
+ // be valid on the receiver side.
+ scoped_ptr<std::string> string_from_ipc_;
CleanupMode cleanup_mode_;
@@ -167,7 +181,6 @@ class PPAPI_PROXY_EXPORT SerializedVar {
};
SerializedVar(VarSerializationRules* serialization_rules);
- SerializedVar(VarSerializationRules* serialization, const PP_Var& var);
mutable scoped_refptr<Inner> inner_;
};
@@ -453,7 +466,9 @@ class PPAPI_PROXY_EXPORT SerializedVarTestReader : public SerializedVar {
// actually want to check.
PP_Var GetIncompleteVar() const { return inner_->GetIncompleteVar(); }
- const std::string& GetString() const { return inner_->GetString(); }
+ const std::string* GetTrackerStringPtr() const {
+ return *inner_->GetStringPtrPtr();
+ }
};
} // namespace proxy
diff --git a/ppapi/proxy/serialized_var_unittest.cc b/ppapi/proxy/serialized_var_unittest.cc
index 494a68d..1ad9348 100644
--- a/ppapi/proxy/serialized_var_unittest.cc
+++ b/ppapi/proxy/serialized_var_unittest.cc
@@ -105,7 +105,7 @@ TEST_F(SerializedVarTest, PluginSerializedStringVarInOutParam) {
// the var tracker should have changed yet, and no messages should have been
// sent.
SerializedVarTestReader reader(sv);
- EXPECT_EQ(kTestString, reader.GetString());
+ EXPECT_EQ(kTestString, *reader.GetTrackerStringPtr());
EXPECT_EQ(2, var_tracker().GetRefCountForObject(plugin_string));
EXPECT_EQ(0u, sink().message_count());
}
diff --git a/ppapi/proxy/var_serialization_rules.h b/ppapi/proxy/var_serialization_rules.h
index b77e834..92d0db8 100644
--- a/ppapi/proxy/var_serialization_rules.h
+++ b/ppapi/proxy/var_serialization_rules.h
@@ -1,10 +1,11 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
#ifndef PPAPI_PROXY_VAR_SERIALIZATION_RULES_H_
#define PPAPI_PROXY_VAR_SERIALIZATION_RULES_H_
+#include "base/memory/scoped_ptr.h"
#include "ppapi/c/pp_var.h"
#include <string>
@@ -27,27 +28,32 @@ class VarSerializationRules {
// argument. The caller has a reference to the var, and the caller is
// responsible for freeing that reference.
- // Prepares the given var for sending to the callee. If the var is a string,
- // the value of that string will be placed in *str_val. If the var is not
- // a string, str_val will be untouched and may be NULL. The return value will
- // be the var valid for the host process.
- virtual PP_Var SendCallerOwned(const PP_Var& var, std::string* str_val) = 0;
+ // Prepares the given var for sending to the remote process. If the var is a
+ // string, *str_ptr_out will be set to point to the string in the tracker
+ // referenced by var. If the var is not a string, *str_ptr_out will be
+ // untouched and may be NULL. For object vars, the returned var will contain
+ // the id valid for the host process. Otherwise, the returned var is valid in
+ // the local process.
+ virtual PP_Var SendCallerOwned(const PP_Var& var,
+ const std::string** str_ptr_out) = 0;
// When receiving a caller-owned variable, normally we don't have to do
// anything. However, in the case of strings, we need to deserialize the
// string from IPC, create a new PP_Var string in the local process, call the
// function, and then destroy the temporary string. These two functions
- // handle that process
+ // handle that process.
//
// BeginReceiveCallerOwned takes a var from IPC and an optional pointer to
// the deserialized string (which will be used only when var is a
// VARTYPE_STRING and may be NULL otherwise) and returns a new var
// representing the input in the local process.
//
- // EndReceiveCallerOwned destroys the string created by Begin* and does
- // nothing otherwise. It should be called with the result of Begin*.
+ // EndReceiveCallerOwned releases the reference count in the Var tracker for
+ // the object or string that was added to the tracker. (Note, if the recipient
+ // took a reference to the Var, it will remain in the tracker after
+ // EndReceiveCallerOwned).
virtual PP_Var BeginReceiveCallerOwned(const PP_Var& var,
- const std::string* str_val,
+ scoped_ptr<std::string> str,
Dispatcher* dispatcher) = 0;
virtual void EndReceiveCallerOwned(const PP_Var& var) = 0;
@@ -65,18 +71,21 @@ class VarSerializationRules {
// deserialized var and deserialized string (which will be used only when var
// is a VARTYPE_STRING and may be NULL otherwise). The input var/string
// should be the result of calling SendPassRef in the remote process. The
- // return value is the var valid in the plugin process.
+ // return value is the var valid in the host process for object vars.
+ // Otherwise, the return value is a var which is valid in the local process.
virtual PP_Var ReceivePassRef(const PP_Var& var,
- const std::string& str_val,
+ scoped_ptr<std::string> str,
Dispatcher* dispatcher) = 0;
// Prepares a var to be sent to the remote side. One local reference will
// be passed to the remote side. Call Begin* before doing the send and End*
// after doing the send. See SendCallerOwned for a description of the string.
//
- // The return value from BeginSendPassRef will be the var valid for the host
- // process. This same value must be passed to EndSendPassRef.
- virtual PP_Var BeginSendPassRef(const PP_Var& var, std::string* str_val) = 0;
+ // For object vars, the return value from BeginSendPassRef will be the var
+ // valid for the host process. Otherwise, it is a var that is valid in the
+ // local process. This same var must be passed to EndSendPassRef.
+ virtual PP_Var BeginSendPassRef(const PP_Var& var,
+ const std::string** str_ptr_out) = 0;
virtual void EndSendPassRef(const PP_Var& var, Dispatcher* dispatcher) = 0;
// ---------------------------------------------------------------------------
diff --git a/ppapi/shared_impl/var.cc b/ppapi/shared_impl/var.cc
index 60d439b..d7b0dac 100644
--- a/ppapi/shared_impl/var.cc
+++ b/ppapi/shared_impl/var.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -124,6 +124,11 @@ StringVar::StringVar(const char* str, uint32 len)
StringVar::~StringVar() {
}
+StringVar::StringVar(scoped_ptr<std::string> str) {
+ // Swap the given string's contents in to value to avoid copying.
+ str->swap(value_);
+}
+
StringVar* StringVar::AsStringVar() {
return this;
}
@@ -146,6 +151,17 @@ PP_Var StringVar::StringToPPVar(const char* data, uint32 len) {
}
// static
+PP_Var StringVar::StringToPPVar(scoped_ptr<std::string> str) {
+ DCHECK(str.get());
+ if (!str.get())
+ return PP_MakeNull();
+ scoped_refptr<StringVar> str_var(new StringVar(str.Pass()));
+ if (!str_var || !IsStringUTF8(str_var->value()))
+ return PP_MakeNull();
+ return str_var->GetPPVar();
+}
+
+// static
StringVar* StringVar::FromPPVar(PP_Var var) {
if (var.type != PP_VARTYPE_STRING)
return NULL;
diff --git a/ppapi/shared_impl/var.h b/ppapi/shared_impl/var.h
index 4d833ae..ed7f4f1 100644
--- a/ppapi/shared_impl/var.h
+++ b/ppapi/shared_impl/var.h
@@ -9,6 +9,7 @@
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/shared_impl/ppapi_shared_export.h"
@@ -93,9 +94,16 @@ class PPAPI_SHARED_EXPORT StringVar : public Var {
public:
StringVar(const std::string& str);
StringVar(const char* str, uint32 len);
+ StringVar(scoped_ptr<std::string> str);
virtual ~StringVar();
const std::string& value() const { return value_; }
+ // Return a pointer to the internal string. This allows other objects to
+ // temporarily store a weak pointer to our internal string. Use with care; the
+ // pointer *will* become invalid if this StringVar is removed from the
+ // tracker. (All of this applies to value(), but this one's even easier to use
+ // dangerously).
+ const std::string* ptr() const { return &value_; }
// Var override.
virtual StringVar* AsStringVar() OVERRIDE;
@@ -109,6 +117,7 @@ class PPAPI_SHARED_EXPORT StringVar : public Var {
// create a StringVar and return the reference to it in the var.
static PP_Var StringToPPVar(const std::string& str);
static PP_Var StringToPPVar(const char* str, uint32 len);
+ static PP_Var StringToPPVar(scoped_ptr<std::string> str);
// Helper function that converts a PP_Var to a string. This will return NULL
// if the PP_Var is not of string type or the string is invalid.