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

Unified Diff: test/cctest/test-unboxed-doubles.cc

Issue 391693002: In-object double fields unboxing (for 64-bit only). (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebasing Created 6 years, 1 month 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
« no previous file with comments | « test/cctest/test-heap.cc ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/cctest/test-unboxed-doubles.cc
diff --git a/test/cctest/test-unboxed-doubles.cc b/test/cctest/test-unboxed-doubles.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2abf3c2926c434a5ff9c2a41ebc55c9dd026bf37
--- /dev/null
+++ b/test/cctest/test-unboxed-doubles.cc
@@ -0,0 +1,668 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdlib.h>
+#include <utility>
+
+#include "src/v8.h"
+
+#include "src/compilation-cache.h"
+#include "src/execution.h"
+#include "src/factory.h"
+#include "src/global-handles.h"
+#include "src/ic/ic.h"
+#include "src/macro-assembler.h"
+#include "test/cctest/cctest.h"
+
+using namespace v8::base;
+using namespace v8::internal;
+
+#if (V8_DOUBLE_FIELDS_UNBOXING)
+
+
+static double GetDoubleFieldValue(JSObject* obj, FieldIndex field_index) {
+ if (obj->IsUnboxedDoubleField(field_index)) {
+ return obj->RawFastDoublePropertyAt(field_index);
+ } else {
+ Object* value = obj->RawFastPropertyAt(field_index);
+ DCHECK(value->IsMutableHeapNumber());
+ return HeapNumber::cast(value)->value();
+ }
+}
+
+
+enum PropertyKind {
+ PROP_CONSTANT,
+ PROP_SMI,
+ PROP_DOUBLE,
+ PROP_TAGGED,
+ PROP_KIND_NUMBER,
+};
+
+static Representation representations[PROP_KIND_NUMBER] = {
+ Representation::None(), Representation::Smi(), Representation::Double(),
+ Representation::Tagged()};
+
+
+static Handle<DescriptorArray> CreateDescriptorArray(Isolate* isolate,
+ PropertyKind* props,
+ int kPropsCount) {
+ Factory* factory = isolate->factory();
+
+ Handle<String> func_name = factory->InternalizeUtf8String("func");
+ Handle<JSFunction> func = factory->NewFunction(func_name);
+
+ Handle<DescriptorArray> descriptors =
+ DescriptorArray::Allocate(isolate, 0, kPropsCount);
+
+ int next_field_offset = 0;
+ for (int i = 0; i < kPropsCount; i++) {
+ EmbeddedVector<char, 64> buffer;
+ SNPrintF(buffer, "prop%d", i);
+ Handle<String> name = factory->InternalizeUtf8String(buffer.start());
+
+ PropertyKind kind = props[i];
+
+ if (kind == PROP_CONSTANT) {
+ ConstantDescriptor d(name, func, NONE);
+ descriptors->Append(&d);
+
+ } else {
+ FieldDescriptor f(name, next_field_offset, NONE, representations[kind]);
+ next_field_offset += f.GetDetails().field_width_in_words();
+ descriptors->Append(&f);
+ }
+ }
+ return descriptors;
+}
+
+
+TEST(LayoutDescriptorBasicFast) {
+ CcTest::InitializeVM();
+ v8::HandleScope scope(CcTest::isolate());
+
+ LayoutDescriptor* layout_desc = LayoutDescriptor::FastPointerLayout();
+
+ CHECK(!layout_desc->IsSlowLayout());
+ CHECK(layout_desc->IsFastPointerLayout());
+ CHECK_EQ(kSmiValueSize, layout_desc->capacity());
+
+ for (int i = 0; i < kSmiValueSize + 13; i++) {
+ CHECK_EQ(true, layout_desc->IsTagged(i));
+ }
+ CHECK_EQ(true, layout_desc->IsTagged(-1));
+ CHECK_EQ(true, layout_desc->IsTagged(-12347));
+ CHECK_EQ(true, layout_desc->IsTagged(15635));
+ CHECK(layout_desc->IsFastPointerLayout());
+
+ for (int i = 0; i < kSmiValueSize; i++) {
+ layout_desc = layout_desc->SetTaggedForTesting(i, false);
+ CHECK_EQ(false, layout_desc->IsTagged(i));
+ layout_desc = layout_desc->SetTaggedForTesting(i, true);
+ CHECK_EQ(true, layout_desc->IsTagged(i));
+ }
+ CHECK(layout_desc->IsFastPointerLayout());
+}
+
+
+TEST(LayoutDescriptorBasicSlow) {
+ CcTest::InitializeVM();
+ Isolate* isolate = CcTest::i_isolate();
+ v8::HandleScope scope(CcTest::isolate());
+
+ Handle<LayoutDescriptor> layout_descriptor;
+ const int kPropsCount = kSmiValueSize * 3;
+ PropertyKind props[kPropsCount];
+ for (int i = 0; i < kPropsCount; i++) {
+ // All properties tagged.
+ props[i] = PROP_TAGGED;
+ }
+
+ {
+ Handle<DescriptorArray> descriptors =
+ CreateDescriptorArray(isolate, props, kPropsCount);
+
+ Handle<Map> map = Map::Create(isolate, kPropsCount);
+
+ layout_descriptor = LayoutDescriptor::New(map, descriptors, kPropsCount);
+ CHECK_EQ(LayoutDescriptor::FastPointerLayout(), *layout_descriptor);
+ CHECK_EQ(kSmiValueSize, layout_descriptor->capacity());
+ map->InitializeDescriptors(*descriptors, *layout_descriptor);
+ DCHECK(layout_descriptor->IsConsistentWithMap(*map));
+ }
+
+ props[0] = PROP_DOUBLE;
+ props[kPropsCount - 1] = PROP_DOUBLE;
+
+ Handle<DescriptorArray> descriptors =
+ CreateDescriptorArray(isolate, props, kPropsCount);
+
+ {
+ int inobject_properties = kPropsCount - 1;
+ Handle<Map> map = Map::Create(isolate, inobject_properties);
+
+ // Should be fast as the only double property is the first one.
+ layout_descriptor = LayoutDescriptor::New(map, descriptors, kPropsCount);
+ CHECK_NE(LayoutDescriptor::FastPointerLayout(), *layout_descriptor);
+ CHECK(!layout_descriptor->IsSlowLayout());
+ CHECK(!layout_descriptor->IsFastPointerLayout());
+
+ CHECK_EQ(false, layout_descriptor->IsTagged(0));
+ for (int i = 1; i < kPropsCount; i++) {
+ CHECK_EQ(true, layout_descriptor->IsTagged(i));
+ }
+ map->InitializeDescriptors(*descriptors, *layout_descriptor);
+ DCHECK(layout_descriptor->IsConsistentWithMap(*map));
+ }
+
+ {
+ int inobject_properties = kPropsCount;
+ Handle<Map> map = Map::Create(isolate, inobject_properties);
+
+ layout_descriptor = LayoutDescriptor::New(map, descriptors, kPropsCount);
+ CHECK_NE(LayoutDescriptor::FastPointerLayout(), *layout_descriptor);
+ CHECK(layout_descriptor->IsSlowLayout());
+ CHECK(!layout_descriptor->IsFastPointerLayout());
+ CHECK(layout_descriptor->capacity() > kSmiValueSize);
+
+ CHECK_EQ(false, layout_descriptor->IsTagged(0));
+ CHECK_EQ(false, layout_descriptor->IsTagged(kPropsCount - 1));
+ for (int i = 1; i < kPropsCount - 1; i++) {
+ CHECK_EQ(true, layout_descriptor->IsTagged(i));
+ }
+
+ map->InitializeDescriptors(*descriptors, *layout_descriptor);
+ DCHECK(layout_descriptor->IsConsistentWithMap(*map));
+
+ // Here we have truly slow layout descriptor, so play with the bits.
+ CHECK_EQ(true, layout_descriptor->IsTagged(-1));
+ CHECK_EQ(true, layout_descriptor->IsTagged(-12347));
+ CHECK_EQ(true, layout_descriptor->IsTagged(15635));
+
+ LayoutDescriptor* layout_desc = *layout_descriptor;
+ // Play with the bits but leave it in consistent state with map at the end.
+ for (int i = 1; i < kPropsCount - 1; i++) {
+ layout_desc = layout_desc->SetTaggedForTesting(i, false);
+ CHECK_EQ(false, layout_desc->IsTagged(i));
+ layout_desc = layout_desc->SetTaggedForTesting(i, true);
+ CHECK_EQ(true, layout_desc->IsTagged(i));
+ }
+ CHECK(layout_desc->IsSlowLayout());
+ CHECK(!layout_desc->IsFastPointerLayout());
+
+ DCHECK(layout_descriptor->IsConsistentWithMap(*map));
+ }
+}
+
+
+TEST(LayoutDescriptorCreateNewFast) {
+ CcTest::InitializeVM();
+ Isolate* isolate = CcTest::i_isolate();
+ v8::HandleScope scope(CcTest::isolate());
+
+ Handle<LayoutDescriptor> layout_descriptor;
+ PropertyKind props[] = {
+ PROP_CONSTANT,
+ PROP_TAGGED, // field #0
+ PROP_CONSTANT,
+ PROP_DOUBLE, // field #1
+ PROP_CONSTANT,
+ PROP_TAGGED, // field #2
+ PROP_CONSTANT,
+ };
+ const int kPropsCount = arraysize(props);
+
+ Handle<DescriptorArray> descriptors =
+ CreateDescriptorArray(isolate, props, kPropsCount);
+
+ {
+ Handle<Map> map = Map::Create(isolate, 0);
+ layout_descriptor = LayoutDescriptor::New(map, descriptors, kPropsCount);
+ CHECK_EQ(LayoutDescriptor::FastPointerLayout(), *layout_descriptor);
+ map->InitializeDescriptors(*descriptors, *layout_descriptor);
+ DCHECK(layout_descriptor->IsConsistentWithMap(*map));
+ }
+
+ {
+ Handle<Map> map = Map::Create(isolate, 1);
+ layout_descriptor = LayoutDescriptor::New(map, descriptors, kPropsCount);
+ CHECK_EQ(LayoutDescriptor::FastPointerLayout(), *layout_descriptor);
+ map->InitializeDescriptors(*descriptors, *layout_descriptor);
+ DCHECK(layout_descriptor->IsConsistentWithMap(*map));
+ }
+
+ {
+ Handle<Map> map = Map::Create(isolate, 2);
+ layout_descriptor = LayoutDescriptor::New(map, descriptors, kPropsCount);
+ CHECK_NE(LayoutDescriptor::FastPointerLayout(), *layout_descriptor);
+ CHECK(!layout_descriptor->IsSlowLayout());
+ CHECK_EQ(true, layout_descriptor->IsTagged(0));
+ CHECK_EQ(false, layout_descriptor->IsTagged(1));
+ CHECK_EQ(true, layout_descriptor->IsTagged(2));
+ CHECK_EQ(true, layout_descriptor->IsTagged(125));
+ map->InitializeDescriptors(*descriptors, *layout_descriptor);
+ DCHECK(layout_descriptor->IsConsistentWithMap(*map));
+ }
+}
+
+
+TEST(LayoutDescriptorCreateNewSlow) {
+ CcTest::InitializeVM();
+ Isolate* isolate = CcTest::i_isolate();
+ v8::HandleScope scope(CcTest::isolate());
+
+ Handle<LayoutDescriptor> layout_descriptor;
+ const int kPropsCount = kSmiValueSize * 3;
+ PropertyKind props[kPropsCount];
+ for (int i = 0; i < kPropsCount; i++) {
+ props[i] = static_cast<PropertyKind>(i % PROP_KIND_NUMBER);
+ }
+
+ Handle<DescriptorArray> descriptors =
+ CreateDescriptorArray(isolate, props, kPropsCount);
+
+ {
+ Handle<Map> map = Map::Create(isolate, 0);
+ layout_descriptor = LayoutDescriptor::New(map, descriptors, kPropsCount);
+ CHECK_EQ(LayoutDescriptor::FastPointerLayout(), *layout_descriptor);
+ map->InitializeDescriptors(*descriptors, *layout_descriptor);
+ DCHECK(layout_descriptor->IsConsistentWithMap(*map));
+ }
+
+ {
+ Handle<Map> map = Map::Create(isolate, 1);
+ layout_descriptor = LayoutDescriptor::New(map, descriptors, kPropsCount);
+ CHECK_EQ(LayoutDescriptor::FastPointerLayout(), *layout_descriptor);
+ map->InitializeDescriptors(*descriptors, *layout_descriptor);
+ DCHECK(layout_descriptor->IsConsistentWithMap(*map));
+ }
+
+ {
+ Handle<Map> map = Map::Create(isolate, 2);
+ layout_descriptor = LayoutDescriptor::New(map, descriptors, kPropsCount);
+ CHECK_NE(LayoutDescriptor::FastPointerLayout(), *layout_descriptor);
+ CHECK(!layout_descriptor->IsSlowLayout());
+ CHECK_EQ(true, layout_descriptor->IsTagged(0));
+ CHECK_EQ(false, layout_descriptor->IsTagged(1));
+ CHECK_EQ(true, layout_descriptor->IsTagged(2));
+ CHECK_EQ(true, layout_descriptor->IsTagged(125));
+ map->InitializeDescriptors(*descriptors, *layout_descriptor);
+ DCHECK(layout_descriptor->IsConsistentWithMap(*map));
+ }
+
+ {
+ int inobject_properties = kPropsCount / 2;
+ Handle<Map> map = Map::Create(isolate, inobject_properties);
+ layout_descriptor = LayoutDescriptor::New(map, descriptors, kPropsCount);
+ CHECK_NE(LayoutDescriptor::FastPointerLayout(), *layout_descriptor);
+ CHECK(layout_descriptor->IsSlowLayout());
+ for (int i = 0; i < inobject_properties; i++) {
+ // PROP_DOUBLE has index 1 among FIELD properties.
+ const bool tagged = (i % (PROP_KIND_NUMBER - 1)) != 1;
+ CHECK_EQ(tagged, layout_descriptor->IsTagged(i));
+ }
+ // Every property after inobject_properties must be tagged.
+ for (int i = inobject_properties; i < kPropsCount; i++) {
+ CHECK_EQ(true, layout_descriptor->IsTagged(i));
+ }
+ map->InitializeDescriptors(*descriptors, *layout_descriptor);
+ DCHECK(layout_descriptor->IsConsistentWithMap(*map));
+
+ // Now test LayoutDescriptor::cast_gc_safe().
+ Handle<LayoutDescriptor> layout_descriptor_copy =
+ LayoutDescriptor::New(map, descriptors, kPropsCount);
+
+ LayoutDescriptor* layout_desc = *layout_descriptor;
+ CHECK_EQ(layout_desc, LayoutDescriptor::cast(layout_desc));
+ CHECK_EQ(layout_desc, LayoutDescriptor::cast_gc_safe(layout_desc));
+ CHECK(layout_descriptor->IsFixedTypedArrayBase());
+ // Now make it look like a forwarding pointer to layout_descriptor_copy.
+ MapWord map_word = layout_desc->map_word();
+ CHECK(!map_word.IsForwardingAddress());
+ layout_desc->set_map_word(
+ MapWord::FromForwardingAddress(*layout_descriptor_copy));
+ CHECK(layout_desc->map_word().IsForwardingAddress());
+ CHECK_EQ(*layout_descriptor_copy,
+ LayoutDescriptor::cast_gc_safe(layout_desc));
+
+ // Restore it back.
+ layout_desc->set_map_word(map_word);
+ CHECK_EQ(layout_desc, LayoutDescriptor::cast(layout_desc));
+ }
+}
+
+
+static Handle<LayoutDescriptor> TestLayoutDescriptorAppend(
+ Isolate* isolate, int inobject_properties, PropertyKind* props,
+ int kPropsCount) {
+ Factory* factory = isolate->factory();
+
+ Handle<String> func_name = factory->InternalizeUtf8String("func");
+ Handle<JSFunction> func = factory->NewFunction(func_name);
+
+ Handle<DescriptorArray> descriptors =
+ DescriptorArray::Allocate(isolate, 0, kPropsCount);
+
+ Handle<Map> map = Map::Create(isolate, inobject_properties);
+ map->InitializeDescriptors(*descriptors,
+ LayoutDescriptor::FastPointerLayout());
+
+ int next_field_offset = 0;
+ for (int i = 0; i < kPropsCount; i++) {
+ EmbeddedVector<char, 64> buffer;
+ SNPrintF(buffer, "prop%d", i);
+ Handle<String> name = factory->InternalizeUtf8String(buffer.start());
+
+ Handle<LayoutDescriptor> layout_descriptor;
+ PropertyKind kind = props[i];
+ if (kind == PROP_CONSTANT) {
+ ConstantDescriptor d(name, func, NONE);
+ layout_descriptor = LayoutDescriptor::Append(map, d.GetDetails());
+ descriptors->Append(&d);
+
+ } else {
+ FieldDescriptor f(name, next_field_offset, NONE, representations[kind]);
+ int field_width_in_words = f.GetDetails().field_width_in_words();
+ next_field_offset += field_width_in_words;
+ layout_descriptor = LayoutDescriptor::Append(map, f.GetDetails());
+ descriptors->Append(&f);
+
+ int field_index = f.GetDetails().field_index();
+ bool is_inobject = field_index < map->inobject_properties();
+ for (int bit = 0; bit < field_width_in_words; bit++) {
+ CHECK_EQ(is_inobject && (kind == PROP_DOUBLE),
+ !layout_descriptor->IsTagged(field_index + bit));
+ }
+ CHECK(layout_descriptor->IsTagged(next_field_offset));
+ }
+ map->InitializeDescriptors(*descriptors, *layout_descriptor);
+ }
+ Handle<LayoutDescriptor> layout_descriptor(map->layout_descriptor(), isolate);
+ DCHECK(layout_descriptor->IsConsistentWithMap(*map));
+ return layout_descriptor;
+}
+
+
+TEST(LayoutDescriptorAppend) {
+ CcTest::InitializeVM();
+ Isolate* isolate = CcTest::i_isolate();
+ v8::HandleScope scope(CcTest::isolate());
+
+ Handle<LayoutDescriptor> layout_descriptor;
+ const int kPropsCount = kSmiValueSize * 3;
+ PropertyKind props[kPropsCount];
+ for (int i = 0; i < kPropsCount; i++) {
+ props[i] = static_cast<PropertyKind>(i % PROP_KIND_NUMBER);
+ }
+
+ layout_descriptor =
+ TestLayoutDescriptorAppend(isolate, 0, props, kPropsCount);
+ CHECK(!layout_descriptor->IsSlowLayout());
+
+ layout_descriptor =
+ TestLayoutDescriptorAppend(isolate, 13, props, kPropsCount);
+ CHECK(!layout_descriptor->IsSlowLayout());
+
+ layout_descriptor =
+ TestLayoutDescriptorAppend(isolate, kSmiValueSize, props, kPropsCount);
+ CHECK(!layout_descriptor->IsSlowLayout());
+
+ layout_descriptor = TestLayoutDescriptorAppend(isolate, kSmiValueSize * 2,
+ props, kPropsCount);
+ CHECK(layout_descriptor->IsSlowLayout());
+
+ layout_descriptor =
+ TestLayoutDescriptorAppend(isolate, kPropsCount, props, kPropsCount);
+ CHECK(layout_descriptor->IsSlowLayout());
+}
+
+
+TEST(LayoutDescriptorAppendAllDoubles) {
+ CcTest::InitializeVM();
+ Isolate* isolate = CcTest::i_isolate();
+ v8::HandleScope scope(CcTest::isolate());
+
+ Handle<LayoutDescriptor> layout_descriptor;
+ const int kPropsCount = kSmiValueSize * 3;
+ PropertyKind props[kPropsCount];
+ for (int i = 0; i < kPropsCount; i++) {
+ props[i] = PROP_DOUBLE;
+ }
+
+ layout_descriptor =
+ TestLayoutDescriptorAppend(isolate, 0, props, kPropsCount);
+ CHECK(!layout_descriptor->IsSlowLayout());
+
+ layout_descriptor =
+ TestLayoutDescriptorAppend(isolate, 13, props, kPropsCount);
+ CHECK(!layout_descriptor->IsSlowLayout());
+
+ layout_descriptor =
+ TestLayoutDescriptorAppend(isolate, kSmiValueSize, props, kPropsCount);
+ CHECK(!layout_descriptor->IsSlowLayout());
+
+ layout_descriptor = TestLayoutDescriptorAppend(isolate, kSmiValueSize + 1,
+ props, kPropsCount);
+ CHECK(layout_descriptor->IsSlowLayout());
+
+ layout_descriptor = TestLayoutDescriptorAppend(isolate, kSmiValueSize * 2,
+ props, kPropsCount);
+ CHECK(layout_descriptor->IsSlowLayout());
+
+ layout_descriptor =
+ TestLayoutDescriptorAppend(isolate, kPropsCount, props, kPropsCount);
+ CHECK(layout_descriptor->IsSlowLayout());
+
+ {
+ // Ensure layout descriptor switches into slow mode at the right moment.
+ layout_descriptor =
+ TestLayoutDescriptorAppend(isolate, kPropsCount, props, kSmiValueSize);
+ CHECK(!layout_descriptor->IsSlowLayout());
+
+ layout_descriptor = TestLayoutDescriptorAppend(isolate, kPropsCount, props,
+ kSmiValueSize + 1);
+ CHECK(layout_descriptor->IsSlowLayout());
+ }
+}
+
+
+static Handle<LayoutDescriptor> TestLayoutDescriptorAppendIfFastOrUseFull(
+ Isolate* isolate, int inobject_properties,
+ Handle<DescriptorArray> descriptors, int number_of_descriptors) {
+ Handle<Map> map = Map::Create(isolate, inobject_properties);
+
+ Handle<LayoutDescriptor> full_layout_descriptor = LayoutDescriptor::New(
+ map, descriptors, descriptors->number_of_descriptors());
+
+ int nof = 0;
+ bool switched_to_slow_mode = false;
+
+ for (int i = 0; i < number_of_descriptors; i++) {
+ PropertyDetails details = descriptors->GetDetails(i);
+
+ // This method calls LayoutDescriptor::AppendIfFastOrUseFull() internally
+ // and does all the required map-descriptors related book keeping.
+ map = Map::CopyInstallDescriptorsForTesting(map, i, descriptors,
+ full_layout_descriptor);
+
+ LayoutDescriptor* layout_desc = map->layout_descriptor();
+
+ if (layout_desc->IsSlowLayout()) {
+ switched_to_slow_mode = true;
+ CHECK_EQ(*full_layout_descriptor, layout_desc);
+ } else {
+ CHECK(!switched_to_slow_mode);
+ if (details.type() == FIELD) {
+ nof++;
+ int field_index = details.field_index();
+ int field_width_in_words = details.field_width_in_words();
+
+ bool is_inobject = field_index < map->inobject_properties();
+ for (int bit = 0; bit < field_width_in_words; bit++) {
+ CHECK_EQ(is_inobject && details.representation().IsDouble(),
+ !layout_desc->IsTagged(field_index + bit));
+ }
+ CHECK(layout_desc->IsTagged(field_index + field_width_in_words));
+ }
+ }
+ DCHECK(map->layout_descriptor()->IsConsistentWithMap(*map));
+ }
+
+ Handle<LayoutDescriptor> layout_descriptor = map->GetLayoutDescriptor();
+ DCHECK(layout_descriptor->IsConsistentWithMap(*map));
+ return layout_descriptor;
+}
+
+
+TEST(LayoutDescriptorAppendIfFastOrUseFull) {
+ CcTest::InitializeVM();
+ Isolate* isolate = CcTest::i_isolate();
+ v8::HandleScope scope(CcTest::isolate());
+
+ Handle<LayoutDescriptor> layout_descriptor;
+ const int kPropsCount = kSmiValueSize * 3;
+ PropertyKind props[kPropsCount];
+ for (int i = 0; i < kPropsCount; i++) {
+ props[i] = static_cast<PropertyKind>(i % PROP_KIND_NUMBER);
+ }
+ Handle<DescriptorArray> descriptors =
+ CreateDescriptorArray(isolate, props, kPropsCount);
+
+ layout_descriptor = TestLayoutDescriptorAppendIfFastOrUseFull(
+ isolate, 0, descriptors, kPropsCount);
+ CHECK(!layout_descriptor->IsSlowLayout());
+
+ layout_descriptor = TestLayoutDescriptorAppendIfFastOrUseFull(
+ isolate, 13, descriptors, kPropsCount);
+ CHECK(!layout_descriptor->IsSlowLayout());
+
+ layout_descriptor = TestLayoutDescriptorAppendIfFastOrUseFull(
+ isolate, kSmiValueSize, descriptors, kPropsCount);
+ CHECK(!layout_descriptor->IsSlowLayout());
+
+ layout_descriptor = TestLayoutDescriptorAppendIfFastOrUseFull(
+ isolate, kSmiValueSize * 2, descriptors, kPropsCount);
+ CHECK(layout_descriptor->IsSlowLayout());
+
+ layout_descriptor = TestLayoutDescriptorAppendIfFastOrUseFull(
+ isolate, kPropsCount, descriptors, kPropsCount);
+ CHECK(layout_descriptor->IsSlowLayout());
+}
+
+
+TEST(LayoutDescriptorAppendIfFastOrUseFullAllDoubles) {
+ CcTest::InitializeVM();
+ Isolate* isolate = CcTest::i_isolate();
+ v8::HandleScope scope(CcTest::isolate());
+
+ Handle<LayoutDescriptor> layout_descriptor;
+ const int kPropsCount = kSmiValueSize * 3;
+ PropertyKind props[kPropsCount];
+ for (int i = 0; i < kPropsCount; i++) {
+ props[i] = PROP_DOUBLE;
+ }
+ Handle<DescriptorArray> descriptors =
+ CreateDescriptorArray(isolate, props, kPropsCount);
+
+ layout_descriptor = TestLayoutDescriptorAppendIfFastOrUseFull(
+ isolate, 0, descriptors, kPropsCount);
+ CHECK(!layout_descriptor->IsSlowLayout());
+
+ layout_descriptor = TestLayoutDescriptorAppendIfFastOrUseFull(
+ isolate, 13, descriptors, kPropsCount);
+ CHECK(!layout_descriptor->IsSlowLayout());
+
+ layout_descriptor = TestLayoutDescriptorAppendIfFastOrUseFull(
+ isolate, kSmiValueSize, descriptors, kPropsCount);
+ CHECK(!layout_descriptor->IsSlowLayout());
+
+ layout_descriptor = TestLayoutDescriptorAppendIfFastOrUseFull(
+ isolate, kSmiValueSize + 1, descriptors, kPropsCount);
+ CHECK(layout_descriptor->IsSlowLayout());
+
+ layout_descriptor = TestLayoutDescriptorAppendIfFastOrUseFull(
+ isolate, kSmiValueSize * 2, descriptors, kPropsCount);
+ CHECK(layout_descriptor->IsSlowLayout());
+
+ layout_descriptor = TestLayoutDescriptorAppendIfFastOrUseFull(
+ isolate, kPropsCount, descriptors, kPropsCount);
+ CHECK(layout_descriptor->IsSlowLayout());
+
+ {
+ // Ensure layout descriptor switches into slow mode at the right moment.
+ layout_descriptor = TestLayoutDescriptorAppendIfFastOrUseFull(
+ isolate, kPropsCount, descriptors, kSmiValueSize);
+ CHECK(!layout_descriptor->IsSlowLayout());
+
+ layout_descriptor = TestLayoutDescriptorAppendIfFastOrUseFull(
+ isolate, kPropsCount, descriptors, kSmiValueSize + 1);
+ CHECK(layout_descriptor->IsSlowLayout());
+ }
+}
+
+
+TEST(StoreBufferScanOnScavenge) {
+ CcTest::InitializeVM();
+ Isolate* isolate = CcTest::i_isolate();
+ Factory* factory = isolate->factory();
+ v8::HandleScope scope(CcTest::isolate());
+
+ CompileRun(
+ "function A() {"
+ " this.x = 42.5;"
+ " this.o = {};"
+ "};"
+ "var o = new A();");
+
+ Handle<String> obj_name = factory->InternalizeUtf8String("o");
+
+ Handle<Object> obj_value =
+ Object::GetProperty(isolate->global_object(), obj_name).ToHandleChecked();
+ CHECK(obj_value->IsJSObject());
+ Handle<JSObject> obj = Handle<JSObject>::cast(obj_value);
+
+ {
+ // Ensure the object is properly set up.
+ Map* map = obj->map();
+ DescriptorArray* descriptors = map->instance_descriptors();
+ CHECK(map->NumberOfOwnDescriptors() == 2);
+ CHECK(descriptors->GetDetails(0).representation().IsDouble());
+ CHECK(descriptors->GetDetails(1).representation().IsHeapObject());
+ FieldIndex field_index = FieldIndex::ForDescriptor(map, 0);
+ CHECK(field_index.is_inobject() && field_index.is_double());
+ CHECK_EQ(FLAG_unbox_double_fields, map->IsUnboxedDoubleField(field_index));
+ CHECK_EQ(42.5, GetDoubleFieldValue(*obj, field_index));
+ }
+ CHECK(isolate->heap()->new_space()->Contains(*obj));
+
+ // Trigger GCs so that the newly allocated object moves to old gen.
+ CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
+ CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
+
+ CHECK(isolate->heap()->old_pointer_space()->Contains(*obj));
+
+ // Create temp object in the new space.
+ Handle<JSArray> temp = factory->NewJSArray(FAST_ELEMENTS, NOT_TENURED);
+ CHECK(isolate->heap()->new_space()->Contains(*temp));
+
+ // Construct a double value that looks like a pointer to the new space object
+ // and store it into the obj.
+ Address fake_object = reinterpret_cast<Address>(*temp) + kPointerSize;
+ double boom_value = bit_cast<double>(fake_object);
+
+ FieldIndex field_index = FieldIndex::ForDescriptor(obj->map(), 0);
+ obj->FastPropertyAtPut(field_index,
+ *factory->NewHeapNumber(boom_value, MUTABLE));
+
+ // Enforce scan on scavenge for the obj's page.
+ MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address());
+ chunk->set_scan_on_scavenge(true);
+
+ // Trigger GCs and force evacuation. Should not crash there.
+ CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
+
+ CHECK_EQ(boom_value, GetDoubleFieldValue(*obj, field_index));
+}
+
+#endif
« no previous file with comments | « test/cctest/test-heap.cc ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698