Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Unified Diff: test/cctest/test-declarative-accessors.cc

Issue 12297012: Runtime version of declarative native accessors. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« test/cctest/SConscript ('K') | « test/cctest/cctest.gyp ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/cctest/test-declarative-accessors.cc
diff --git a/test/cctest/test-declarative-accessors.cc b/test/cctest/test-declarative-accessors.cc
new file mode 100644
index 0000000000000000000000000000000000000000..3bec95744f22b1ddafac705f4896e48554ce0f2d
--- /dev/null
+++ b/test/cctest/test-declarative-accessors.cc
@@ -0,0 +1,405 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "cctest.h"
+
+using namespace v8::internal;
+
+
+template<typename Type>
+struct Checker {
+ static void CheckEq(const Type expected, const Type value) {
+ CHECK_EQ(static_cast<int64_t>(expected), static_cast<int64_t>(value));
+ }
+};
+
+
+template<>
+struct Checker<void*> {
+ static void CheckEq(const void* expected, const void* value) {
+ CHECK_EQ(expected, value);
+ }
+};
+
+
+template<typename Type>
+static void CheckSerialization(const Type expected) {
+ using namespace v8;
+ uint8_t smi_storage[AccessorDescriptorSerialization<Type>::kArraySize];
+ AccessorDescriptorSerialization<Type>::Serialize(expected, smi_storage);
+ const Type value =
+ AccessorDescriptorSerialization<Type>::Deserialize(smi_storage);
+ Checker<Type>::CheckEq(expected, value);
+}
+
+
+template<typename Type>
+static void CheckBounds(Type min, Type max) {
+ CheckSerialization<Type>(static_cast<Type>(0));
+ CheckSerialization(min);
+ CheckSerialization(max);
+}
+
+
+TEST(MemberSerialization) {
+ CheckBounds<v8::AccessorDescriptorDataType>(
+ static_cast<v8::AccessorDescriptorDataType>(0),
+ static_cast<v8::AccessorDescriptorDataType>(INT16_MAX));
+ CheckBounds<v8::AccessorDescriptorType>(
+ static_cast<v8::AccessorDescriptorType>(0),
+ static_cast<v8::AccessorDescriptorType>(INT16_MAX));
+ CheckBounds<uint8_t>(0, UINT8_MAX);
+ CheckBounds<int8_t>(INT8_MIN, INT8_MAX);
+ CheckBounds<uint16_t>(0, INT16_MAX);
+ CheckBounds<int16_t>(INT16_MIN, INT16_MAX);
+ CheckBounds<uint32_t>(0, INT32_MAX);
+ CheckBounds<int32_t>(INT32_MIN, INT32_MAX);
+ CheckBounds<uint64_t>(0, INT64_MAX);
+ CheckBounds<int64_t>(INT64_MIN, INT64_MAX);
+ CheckBounds<void*>(reinterpret_cast<void*>(INTPTR_MIN),
+ reinterpret_cast<void*>(INTPTR_MAX));
+}
+
+
+TEST(DescriptorSerialization) {
+ v8::V8::Initialize();
+ v8::HandleScope scope;
+ LocalContext context;
+ // Create a descriptor.
+ v8::AccessorDescriptor accessor_descriptor =
+ { 6, -12, v8::kDescriptorPointerDereference, { NULL } };
+ v8::AccessorDescriptor sub_descriptor =
+ { 7, -11, v8::kDescriptorPointerCompare, { NULL } };
+ int arbitrary_value;
+ v8::PointerCompareDescriptor pointer_compare_descriptor =
+ { &arbitrary_value };
+ sub_descriptor.pointer_compare_descriptor = pointer_compare_descriptor;
+ accessor_descriptor.derefence_descriptor = &sub_descriptor;
+ // Serialize
+ uint16_t length;
+ uint8_t* storage;
+ {
+ length = DeclaredAccessorDescriptor::SerializedLength(&accessor_descriptor);
+ Handle<DeclaredAccessorDescriptor> descriptor =
+ DeclaredAccessorDescriptor::Create(&accessor_descriptor,
+ Isolate::Current());
+ AssertNoAllocation no_allocation;
+ ByteArray* array = descriptor->serialized_descriptor();
+ CHECK_EQ(length, array->length());
+ storage = new uint8_t[length];
+ for (int i = 0; i < length; i++) {
+ storage[i] = array->get(i);
+ }
+ }
+ // Deserialize
+ AccessorDescriptorDeserializer deserializer(length, storage);
+ v8::AccessorDescriptor deserialized;
+ deserializer.Next(&deserialized);
+ CHECK(!deserializer.Complete());
+ CHECK_EQ(6, deserialized.internal_field);
+ CHECK_EQ(-12, deserialized.byte_offset);
+ CHECK_EQ(v8::kDescriptorPointerDereference, deserialized.type);
+ deserializer.Next(&deserialized);
+ CHECK(deserializer.Complete());
+ CHECK_EQ(7, deserialized.internal_field);
+ CHECK_EQ(-11, deserialized.byte_offset);
+ CHECK_EQ(v8::kDescriptorPointerCompare, deserialized.type);
+ CHECK_EQ(&arbitrary_value,
+ deserialized.pointer_compare_descriptor.compare_value);
+ delete[] storage;
+}
+
+
+class HandleArray : public Malloced {
+ public:
+ static const unsigned kArraySize = 200;
+ explicit HandleArray() {}
+ ~HandleArray() { Reset(v8::Isolate::GetCurrent()); }
+ void Reset(v8::Isolate* isolate) {
+ for (unsigned i = 0; i < kArraySize; i++) {
+ if (handles[i].IsEmpty()) continue;
+ handles[i].Dispose(isolate);
+ handles[i].Clear();
+ }
+ }
+ v8::Persistent<v8::Value> handles[kArraySize];
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HandleArray);
+};
+
+
+// An aligned character array of size 1024.
+class AlignedArray : public Malloced {
+ public:
+ static const unsigned kArraySize = 1024/sizeof(uint64_t);
+ AlignedArray() { Reset(); }
+
+ void Reset() {
+ for (unsigned i = 0; i < kArraySize; i++) {
+ data[i] = 0;
+ }
+ }
+
+ template<typename T>
+ T As() { return reinterpret_cast<T>(data); }
+
+ private:
+ uint64_t data[kArraySize];
+ DISALLOW_COPY_AND_ASSIGN(AlignedArray);
+};
+
+
+class DescriptorTestHelper {
+ public:
+ DescriptorTestHelper() :
+ isolate_(NULL), array_(new AlignedArray), handle_array_(new HandleArray) {
+ v8::V8::Initialize();
+ isolate_ = v8::Isolate::GetCurrent();
+ }
+ v8::Isolate* isolate_;
+ // Data objects.
+ SmartPointer<AlignedArray> array_;
+ SmartPointer<HandleArray> handle_array_;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DescriptorTestHelper);
+};
+
+
+static v8::Local<v8::ObjectTemplate> CreateConstructor(
+ v8::Handle<v8::Context> context,
+ const char* class_name,
+ int internal_fields,
+ const char* descriptor_name = NULL,
+ const v8::AccessorDescriptor* descriptor = NULL) {
+ v8::Local<v8::FunctionTemplate> constructor = v8::FunctionTemplate::New();
+ v8::Local<v8::ObjectTemplate> obj_template = constructor->InstanceTemplate();
+ // Setup object template.
+ if (descriptor_name != NULL && descriptor != NULL) {
+ bool added_accessor =
+ obj_template->SetAccessor(v8_str(descriptor_name), descriptor);
+ CHECK(added_accessor);
+ }
+ obj_template->SetInternalFieldCount(internal_fields);
+ context->Global()->Set(v8_str(class_name), constructor->GetFunction());
+ return obj_template;
+}
+
+
+static void VerifyRead(const v8::AccessorDescriptor* descriptor,
+ void* internal_object,
+ v8::Handle<v8::Value> expected_value,
+ v8::Local<v8::Context> context =
+ v8::Local<v8::Context>()) {
+ v8::HandleScope scope;
+ // Generate a context if necessary and retry.
+ if (context.IsEmpty()) {
+ LocalContext local_context;
+ VerifyRead(descriptor,
+ internal_object,
+ expected_value,
+ local_context.local());
+ return;
+ }
+ int internal_field = descriptor->internal_field;
+ int total_fields = (internal_field+1)*2 + 7;
+ CreateConstructor(context, "Accessible", total_fields, "x", descriptor);
+ // Setup object.
+ CompileRun("var accessible = new Accessible();");
+ v8::Local<v8::Object> obj(
+ v8::Object::Cast(*context->Global()->Get(v8_str("accessible"))));
+ obj->SetAlignedPointerInInternalField(internal_field, internal_object);
+ bool added_accessor;
+ added_accessor = obj->SetAccessor(v8_str("y"), descriptor);
+ CHECK(added_accessor);
+ added_accessor = obj->SetAccessor(v8_str("13"), descriptor);
+ CHECK(added_accessor);
+ // Test access from template getter.
+ v8::Local<v8::Value> value;
+ value = CompileRun("accessible.x;");
+ CHECK_EQ(expected_value, value);
+ value = CompileRun("accessible['x'];");
+ CHECK_EQ(expected_value, value);
+ // Test access from object getter.
+ value = CompileRun("accessible.y;");
+ CHECK_EQ(expected_value, value);
+ value = CompileRun("accessible['y'];");
+ CHECK_EQ(expected_value, value);
+ value = CompileRun("accessible[13];");
+ CHECK_EQ(expected_value, value);
+ value = CompileRun("accessible['13'];");
+ CHECK_EQ(expected_value, value);
+}
+
+
+static v8::Handle<v8::Value> Convert(int32_t value, v8::Isolate* isolate) {
+ return v8::Integer::New(value, isolate);
+}
+
+
+static v8::Handle<v8::Value> Convert(float value, v8::Isolate*) {
+ return v8::Number::New(value);
+}
+
+
+static v8::Handle<v8::Value> Convert(double value, v8::Isolate*) {
+ return v8::Number::New(value);
+}
+
+
+template<typename T>
+static void TestPrimitiveValue(T value,
+ v8::AccessorDescriptorDataType data_type,
+ DescriptorTestHelper* helper) {
+ v8::HandleScope handle_scope;
+ int index = 17;
+ v8::AccessorDescriptor descriptor =
+ { 3, index*sizeof(T), v8::kDescriptorPrimitiveValue, { NULL } };
+ v8::PrimitiveValueDescriptor sub_descriptor = { data_type, 0 };
+ descriptor.primitive_value_descriptor = sub_descriptor;
+ v8::Handle<v8::Value> expected = Convert(value, helper->isolate_);
+ helper->array_->Reset();
+ helper->array_->As<T*>()[index] = value;
+ VerifyRead(&descriptor, *helper->array_, expected);
+}
+
+
+TEST(PrimitiveValueRead) {
+ DescriptorTestHelper helper;
+ TestPrimitiveValue<int32_t>(203, v8::kDescriptorInt32Type, &helper);
+ TestPrimitiveValue<float>(23.7f, v8::kDescriptorFloatType, &helper);
+ TestPrimitiveValue<double>(23.7, v8::kDescriptorDoubleType, &helper);
+}
+
+
+template<typename T>
+static void TestBitmaskCompare(uint32_t bitmask,
+ uint32_t compare_value,
+ DescriptorTestHelper* helper) {
+ v8::HandleScope handle_scope;
+ int index = 13;
+ v8::AccessorDescriptor descriptor =
+ { 3, index*sizeof(T), v8::kDescriptorBitmaskCompare, { NULL } };
+ v8::BitmaskCompareDescriptor sub_descriptor =
+ { bitmask, compare_value, sizeof(T) };
+ descriptor.bitmask_compare_descriptor = sub_descriptor;
+ helper->array_->Reset();
+ VerifyRead(&descriptor, *helper->array_, v8::False(helper->isolate_));
+ helper->array_->As<T*>()[index] = compare_value;
+ VerifyRead(&descriptor, *helper->array_, v8::True(helper->isolate_));
+ helper->array_->As<T*>()[index] = compare_value & bitmask;
+ VerifyRead(&descriptor, *helper->array_, v8::True(helper->isolate_));
+}
+
+
+TEST(BitmaskCompareRead) {
+ DescriptorTestHelper helper;
+ TestBitmaskCompare<uint8_t>(0xf3, 0xa8, &helper);
+ TestBitmaskCompare<uint16_t>(0xfefe, 0x7d42, &helper);
+ TestBitmaskCompare<uint32_t>(0xfefeab18, 0x1234fdec, &helper);
+}
+
+
+TEST(PointerCompareRead) {
+ DescriptorTestHelper helper;
+ v8::HandleScope handle_scope;
+ void* ptr = helper.isolate_;
+ int index = 35;
+ v8::AccessorDescriptor descriptor =
+ { 3, index * sizeof(ptr), v8::kDescriptorPointerCompare, { NULL } };
+ v8::PointerCompareDescriptor sub_descriptor = { ptr };
+ descriptor.pointer_compare_descriptor = sub_descriptor;
+ VerifyRead(&descriptor, *helper.array_, v8::False(helper.isolate_));
+ helper.array_->As<uintptr_t*>()[index] = reinterpret_cast<uintptr_t>(ptr);
+ VerifyRead(&descriptor, *helper.array_, v8::True(helper.isolate_));
+}
+
+
+TEST(PointerDeferenceRead) {
+ DescriptorTestHelper helper;
+ v8::HandleScope handle_scope;
+ int first_index = 13;
+ int pointed_to_index = 75;
+ int second_index = 11;
+ uint16_t expected = 0x1425;
+ v8::AccessorDescriptor descriptor =
+ { 3, first_index*kPointerSize, v8::kDescriptorPointerDereference,
+ { NULL } };
+ v8::AccessorDescriptor sub_descriptor =
+ { 0, second_index*sizeof(int16_t), v8::kDescriptorPrimitiveValue,
+ { NULL } };
+ v8::PrimitiveValueDescriptor sub_sub_descriptor =
+ { v8::kDescriptorInt16Type, 0 };
+ descriptor.derefence_descriptor = &sub_descriptor;
+ sub_descriptor.primitive_value_descriptor = sub_sub_descriptor;
+ AlignedArray* array = *helper.array_;
+ array->As<uintptr_t**>()[first_index] =
+ &array->As<uintptr_t*>()[pointed_to_index];
+ VerifyRead(&descriptor, array, v8::Integer::New(0));
+ second_index += pointed_to_index*sizeof(uintptr_t)/sizeof(uint16_t);
+ array->As<uint16_t*>()[second_index] = expected;
+ VerifyRead(&descriptor, array, v8::Integer::New(expected));
+}
+
+TEST(HandleDeferenceRead) {
+ DescriptorTestHelper helper;
+ v8::HandleScope handle_scope;
+ int first_index = 13;
+ int second_index = 11;
+ uint16_t expected = 0x1425;
+ v8::AccessorDescriptor descriptor =
+ { 3, first_index*kPointerSize, v8::kDescriptorInternalFieldDereference,
+ { NULL } };
+ v8::AccessorDescriptor sub_descriptor =
+ { 2, second_index*sizeof(int16_t), v8::kDescriptorPrimitiveValue,
+ { NULL } };
+ v8::PrimitiveValueDescriptor sub_sub_descriptor =
+ { v8::kDescriptorInt16Type, 0 };
+ descriptor.derefence_descriptor = &sub_descriptor;
+ sub_descriptor.primitive_value_descriptor = sub_sub_descriptor;
+ // Setup object.
+ LocalContext local_context;
+ v8::Local<v8::Context> context = local_context.local();
+ v8::Local<v8::Object> object;
+ {
+ CreateConstructor(context, "SomeObject", 7);
+ CompileRun("var some_object = new SomeObject();");
+ v8::Local<v8::Object> object(
+ v8::Object::Cast(*context->Global()->Get(v8_str("some_object"))));
+ object->SetAlignedPointerInInternalField(
+ sub_descriptor.internal_field, *helper.array_);
+ helper.handle_array_->handles[first_index] =
+ v8::Persistent<v8::Value>::New(helper.isolate_, object);
+ }
+ VerifyRead(&descriptor, *helper.handle_array_, v8::Integer::New(0), context);
+ helper.array_->As<uint16_t*>()[second_index] = expected;
+ VerifyRead(&descriptor, *helper.handle_array_, v8::Integer::New(expected));
+}
+
« test/cctest/SConscript ('K') | « test/cctest/cctest.gyp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698