Landing patch by tonyg@chromium.org:

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


git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4710 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
ager@chromium.org 2010-05-25 06:38:19 +00:00
parent 0328e0cf3a
commit ab6055d85d
6 changed files with 93 additions and 15 deletions

View File

@ -512,11 +512,37 @@ class V8EXPORT Data {
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;
};

View File

@ -1105,8 +1105,19 @@ ScriptData* ScriptData::PreCompile(const char* input, int length) {
}
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));
}

View File

@ -139,7 +139,8 @@ Object* Object::GetPropertyWithReceiver(Object* receiver,
}
Object* Object::GetPropertyWithCallback(Object* receiver,
Object* Object::GetPropertyWithCallk
jback(Object* receiver,
Object* structure,
String* name,
Object* holder) {

View File

@ -5073,12 +5073,13 @@ ScriptDataImpl::~ScriptDataImpl() {
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());
}

View File

@ -90,7 +90,7 @@ class ScriptDataImpl : public ScriptData {
last_entry_(0) { }
virtual ~ScriptDataImpl();
virtual int Length();
virtual unsigned* Data();
virtual const char* Data();
virtual bool HasError();
FunctionEntry GetFunctionEnd(int start);
bool SanityCheck();

View File

@ -8003,8 +8003,8 @@ TEST(PreCompile) {
// 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(PreCompile) {
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,14 +8025,53 @@ TEST(PreCompileWithError) {
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
// to use functions that have not yet been compiled. The potential
// problem of loading a function that has not yet been compiled can