Revision: 4710
Author: [email protected]
Date: Mon May 24 23:38:19 2010
Log: Landing patch by [email protected]:

Changing ScriptData API to serialize its internal representation to a
const char* array.

This decouples the API from the internal representation and avoids the need for
callers to serialize themselves.

As a side-effect, ScriptData::New() no longer assumes ownership of its input.
This shouldn't matter as typical usage patterns for the old API would have
required a copy prior to calling ScriptData::New().

Review URL: http://codereview.chromium.org/2118010/show

http://code.google.com/p/v8/source/detail?r=4710

Modified:
 /branches/bleeding_edge/include/v8.h
 /branches/bleeding_edge/src/api.cc
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/parser.cc
 /branches/bleeding_edge/src/parser.h
 /branches/bleeding_edge/test/cctest/test-api.cc

=======================================
--- /branches/bleeding_edge/include/v8.h        Sun May  9 23:24:18 2010
+++ /branches/bleeding_edge/include/v8.h        Mon May 24 23:38:19 2010
@@ -512,11 +512,37 @@
 class V8EXPORT ScriptData {  // NOLINT
  public:
   virtual ~ScriptData() { }
+  /**
+   * Pre-compiles the specified script (context-independent).
+   *
+   * \param input Pointer to UTF-8 script source code.
+   * \param length Length of UTF-8 script source code.
+   */
   static ScriptData* PreCompile(const char* input, int length);
-  static ScriptData* New(unsigned* data, int length);
-
+
+  /**
+   * Load previous pre-compilation data.
+   *
+   * \param data Pointer to data returned by a call to Data() of a previous
+   *   ScriptData. Ownership is not transferred.
+   * \param length Length of data.
+   */
+  static ScriptData* New(const char* data, int length);
+
+  /**
+   * Returns the length of Data().
+   */
   virtual int Length() = 0;
-  virtual unsigned* Data() = 0;
+
+  /**
+ * Returns a serialized representation of this ScriptData that can later be
+   * passed to New(). NOTE: Serialized data is platform-dependent.
+   */
+  virtual const char* Data() = 0;
+
+  /**
+   * Returns true if the source code could not be parsed.
+   */
   virtual bool HasError() = 0;
 };

=======================================
--- /branches/bleeding_edge/src/api.cc  Fri May 21 13:52:19 2010
+++ /branches/bleeding_edge/src/api.cc  Mon May 24 23:38:19 2010
@@ -1105,8 +1105,19 @@
 }


-ScriptData* ScriptData::New(unsigned* data, int length) {
-  return new i::ScriptDataImpl(i::Vector<unsigned>(data, length));
+ScriptData* ScriptData::New(const char* data, int length) {
+  // Return an empty ScriptData if the length is obviously invalid.
+  if (length % sizeof(unsigned) != 0) {
+    return new i::ScriptDataImpl(i::Vector<unsigned>());
+  }
+
+  // Copy the data to ensure it is properly aligned.
+  int deserialized_data_length = length / sizeof(unsigned);
+ unsigned* deserialized_data = i::NewArray<unsigned>(deserialized_data_length);
+  memcpy(deserialized_data, data, length);
+
+  return new i::ScriptDataImpl(
+      i::Vector<unsigned>(deserialized_data, deserialized_data_length));
 }


=======================================
--- /branches/bleeding_edge/src/objects.cc      Fri May 21 10:37:47 2010
+++ /branches/bleeding_edge/src/objects.cc      Mon May 24 23:38:19 2010
@@ -139,7 +139,8 @@
 }


-Object* Object::GetPropertyWithCallback(Object* receiver,
+Object* Object::GetPropertyWithCallk
+jback(Object* receiver,
                                         Object* structure,
                                         String* name,
                                         Object* holder) {
=======================================
--- /branches/bleeding_edge/src/parser.cc       Mon May 10 04:32:25 2010
+++ /branches/bleeding_edge/src/parser.cc       Mon May 24 23:38:19 2010
@@ -5073,12 +5073,13 @@


 int ScriptDataImpl::Length() {
-  return store_.length();
+  static const int kCharToUnsignedFactor = sizeof(unsigned) / sizeof(char);
+  return store_.length() * kCharToUnsignedFactor;
 }


-unsigned* ScriptDataImpl::Data() {
-  return store_.start();
+const char* ScriptDataImpl::Data() {
+  return reinterpret_cast<const char*>(store_.start());
 }


=======================================
--- /branches/bleeding_edge/src/parser.h        Thu Mar 11 02:34:29 2010
+++ /branches/bleeding_edge/src/parser.h        Mon May 24 23:38:19 2010
@@ -90,7 +90,7 @@
         last_entry_(0) { }
   virtual ~ScriptDataImpl();
   virtual int Length();
-  virtual unsigned* Data();
+  virtual const char* Data();
   virtual bool HasError();
   FunctionEntry GetFunctionEnd(int start);
   bool SanityCheck();
=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc     Sun May  9 23:24:01 2010
+++ /branches/bleeding_edge/test/cctest/test-api.cc     Mon May 24 23:38:19 2010
@@ -8003,8 +8003,8 @@
// TODO(155): This test would break without the initialization of V8. This is
   // a workaround for now to make this test not fail.
   v8::V8::Initialize();
-  const char *script = "function foo(a) { return a+1; }";
-  v8::ScriptData *sd =
+  const char* script = "function foo(a) { return a+1; }";
+  v8::ScriptData* sd =
       v8::ScriptData::PreCompile(script, i::StrLength(script));
   CHECK_NE(sd->Length(), 0);
   CHECK_NE(sd->Data(), NULL);
@@ -8015,8 +8015,8 @@

 TEST(PreCompileWithError) {
   v8::V8::Initialize();
-  const char *script = "function foo(a) { return 1 * * 2; }";
-  v8::ScriptData *sd =
+  const char* script = "function foo(a) { return 1 * * 2; }";
+  v8::ScriptData* sd =
       v8::ScriptData::PreCompile(script, i::StrLength(script));
   CHECK(sd->HasError());
   delete sd;
@@ -8025,12 +8025,51 @@

 TEST(Regress31661) {
   v8::V8::Initialize();
-  const char *script = " The Definintive Guide";
-  v8::ScriptData *sd =
+  const char* script = " The Definintive Guide";
+  v8::ScriptData* sd =
       v8::ScriptData::PreCompile(script, i::StrLength(script));
   CHECK(sd->HasError());
   delete sd;
 }
+
+
+// Tests that ScriptData can be serialized and deserialized.
+TEST(PreCompileSerialization) {
+  v8::V8::Initialize();
+  const char* script = "function foo(a) { return a+1; }";
+  v8::ScriptData* sd =
+      v8::ScriptData::PreCompile(script, i::StrLength(script));
+
+  // Serialize.
+  int serialized_data_length = sd->Length();
+  char* serialized_data = i::NewArray<char>(serialized_data_length);
+  memcpy(serialized_data, sd->Data(), serialized_data_length);
+
+  // Deserialize.
+  v8::ScriptData* deserialized_sd =
+      v8::ScriptData::New(serialized_data, serialized_data_length);
+
+  // Verify that the original is the same as the deserialized.
+  CHECK_EQ(sd->Length(), deserialized_sd->Length());
+  CHECK_EQ(0, memcmp(sd->Data(), deserialized_sd->Data(), sd->Length()));
+  CHECK_EQ(sd->HasError(), deserialized_sd->HasError());
+
+  delete sd;
+  delete deserialized_sd;
+}
+
+
+// Attempts to deserialize bad data.
+TEST(PreCompileDeserializationError) {
+  v8::V8::Initialize();
+  const char* data = "DONT CARE";
+  int invalid_size = 3;
+  v8::ScriptData* sd = v8::ScriptData::New(data, invalid_size);
+
+  CHECK_EQ(0, sd->Length());
+
+  delete sd;
+}


 // This tests that we do not allow dictionary load/call inline caches

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to