Commit 7dcc70b8 authored by Vicky Kontoura's avatar Vicky Kontoura Committed by Commit Bot

[web snapshot] Support numbers

This CL adds support for integer and double values in web snapshots.

Bug: v8:11525, v8:11706
Change-Id: Ib75c52d440cd51bf78f57eecca09cecf35b801a4
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2854734
Commit-Queue: Vicky Kontoura <vkont@google.com>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74259}
parent 5d2ec36d
......@@ -302,6 +302,9 @@ void ValueSerializer::WriteZigZag(T value) {
(value >> (8 * sizeof(T) - 1)));
}
template EXPORT_TEMPLATE_DEFINE(
V8_EXPORT_PRIVATE) void ValueSerializer::WriteZigZag(int32_t value);
void ValueSerializer::WriteDouble(double value) {
// Warning: this uses host endianness.
WriteRawBytes(&value, sizeof(value));
......
......@@ -390,8 +390,9 @@ void WebSnapshotSerializer::WriteValue(Handle<Object> object,
ValueSerializer& serializer) {
uint32_t id = 0;
if (object->IsSmi()) {
// TODO(v8:11525): Implement.
UNREACHABLE();
serializer.WriteUint32(ValueType::INTEGER);
serializer.WriteZigZag<int32_t>(Smi::cast(*object).value());
return;
}
DCHECK(object->IsHeapObject());
......@@ -400,8 +401,10 @@ void WebSnapshotSerializer::WriteValue(Handle<Object> object,
// TODO(v8:11525): Implement.
UNREACHABLE();
case HEAP_NUMBER_TYPE:
// TODO(v8:11525): Implement.
UNREACHABLE();
// TODO(v8:11525): Handle possible endianness mismatch.
serializer.WriteUint32(ValueType::DOUBLE);
serializer.WriteDouble(HeapNumber::cast(*object).value());
break;
case JS_FUNCTION_TYPE:
SerializeFunction(Handle<JSFunction>::cast(object), id);
serializer.WriteUint32(ValueType::FUNCTION_ID);
......@@ -843,6 +846,26 @@ void WebSnapshotDeserializer::ReadValue(Handle<Object>& value,
return;
}
switch (value_type) {
case ValueType::INTEGER: {
Maybe<int32_t> number = deserializer_->ReadZigZag<int32_t>();
if (number.IsNothing()) {
Throw("Web snapshot: Malformed integer");
return;
}
value = isolate_->factory()->NewNumberFromInt(number.FromJust());
representation = Representation::Tagged();
break;
}
case ValueType::DOUBLE: {
double number;
if (!deserializer_->ReadDouble(&number)) {
Throw("Web snapshot: Malformed double");
return;
}
value = isolate_->factory()->NewNumber(number);
representation = Representation::Tagged();
break;
}
case ValueType::STRING_ID: {
value = ReadString(false);
representation = Representation::Tagged();
......
......@@ -38,7 +38,13 @@ class WebSnapshotSerializerDeserializer {
inline bool has_error() const { return error_message_ != nullptr; }
const char* error_message() const { return error_message_; }
enum ValueType : uint8_t { STRING_ID, OBJECT_ID, FUNCTION_ID };
enum ValueType : uint8_t {
INTEGER,
DOUBLE,
STRING_ID,
OBJECT_ID,
FUNCTION_ID
};
// The maximum count of items for each value type (strings, objects etc.)
static constexpr uint32_t kMaxItemCount =
......
......@@ -12,10 +12,11 @@ namespace internal {
namespace {
void TestWebSnapshot(const char* snapshot_source, const char* test_source,
const char* expected_result, uint32_t string_count,
uint32_t map_count, uint32_t context_count,
uint32_t function_count, uint32_t object_count) {
void TestWebSnapshotExtensive(
const char* snapshot_source, const char* test_source,
std::function<void(v8::Isolate*, v8::Local<v8::Context>)> tester,
uint32_t string_count, uint32_t map_count, uint32_t context_count,
uint32_t function_count, uint32_t object_count) {
CcTest::InitializeVM();
v8::Isolate* isolate = CcTest::isolate();
......@@ -47,8 +48,7 @@ void TestWebSnapshot(const char* snapshot_source, const char* test_source,
CHECK(deserializer.UseWebSnapshot(snapshot_data.buffer,
snapshot_data.buffer_size));
CHECK(!deserializer.has_error());
v8::Local<v8::String> result = CompileRun(test_source).As<v8::String>();
CHECK(result->Equals(new_context, v8_str(expected_result)).FromJust());
tester(isolate, new_context);
CHECK_EQ(string_count, deserializer.string_count());
CHECK_EQ(map_count, deserializer.map_count());
CHECK_EQ(context_count, deserializer.context_count());
......@@ -57,6 +57,20 @@ void TestWebSnapshot(const char* snapshot_source, const char* test_source,
}
}
void TestWebSnapshot(const char* snapshot_source, const char* test_source,
const char* expected_result, uint32_t string_count,
uint32_t map_count, uint32_t context_count,
uint32_t function_count, uint32_t object_count) {
TestWebSnapshotExtensive(
snapshot_source, test_source,
[test_source, expected_result](v8::Isolate* isolate,
v8::Local<v8::Context> new_context) {
v8::Local<v8::String> result = CompileRun(test_source).As<v8::String>();
CHECK(result->Equals(new_context, v8_str(expected_result)).FromJust());
},
string_count, map_count, context_count, function_count, object_count);
}
} // namespace
TEST(Minimal) {
......@@ -72,6 +86,60 @@ TEST(Minimal) {
kMapCount, kContextCount, kFunctionCount, kObjectCount);
}
TEST(Numbers) {
const char* snapshot_source =
"var foo = {'a': 6,\n"
" 'b': -11,\n"
" 'c': 11.6,\n"
" 'd': NaN,\n"
" 'e': Number.POSITIVE_INFINITY,\n"
" 'f': Number.NEGATIVE_INFINITY,\n"
"}";
const char* test_source = "foo";
uint32_t kStringCount = 7; // 'foo', 'a', ..., 'f'
uint32_t kMapCount = 1;
uint32_t kContextCount = 0;
uint32_t kFunctionCount = 0;
uint32_t kObjectCount = 1;
std::function<void(v8::Isolate*, v8::Local<v8::Context>)> tester =
[test_source](v8::Isolate* isolate, v8::Local<v8::Context> new_context) {
v8::Local<v8::Object> result = CompileRun(test_source).As<v8::Object>();
int32_t a = result->Get(new_context, v8_str("a"))
.ToLocalChecked()
.As<v8::Number>()
->Value();
CHECK_EQ(a, 6);
int32_t b = result->Get(new_context, v8_str("b"))
.ToLocalChecked()
.As<v8::Number>()
->Value();
CHECK_EQ(b, -11);
double c = result->Get(new_context, v8_str("c"))
.ToLocalChecked()
.As<v8::Number>()
->Value();
CHECK_EQ(c, 11.6);
double d = result->Get(new_context, v8_str("d"))
.ToLocalChecked()
.As<v8::Number>()
->Value();
CHECK(std::isnan(d));
double e = result->Get(new_context, v8_str("e"))
.ToLocalChecked()
.As<v8::Number>()
->Value();
CHECK_EQ(e, std::numeric_limits<double>::infinity());
double f = result->Get(new_context, v8_str("f"))
.ToLocalChecked()
.As<v8::Number>()
->Value();
CHECK_EQ(f, -std::numeric_limits<double>::infinity());
};
TestWebSnapshotExtensive(snapshot_source, test_source, tester, kStringCount,
kMapCount, kContextCount, kFunctionCount,
kObjectCount);
}
TEST(Function) {
const char* snapshot_source =
"var foo = {'key': function() { return '11525'; }};";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment