2016-12-19 12:50:30 +00:00
|
|
|
// Copyright 2016 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 <cmath>
|
|
|
|
#include <iostream>
|
|
|
|
#include <limits>
|
|
|
|
|
2019-05-17 12:13:44 +00:00
|
|
|
#include "src/api/api-inl.h"
|
2019-05-21 09:30:15 +00:00
|
|
|
#include "src/codegen/compiler.h"
|
2018-05-17 12:28:56 +00:00
|
|
|
#include "src/objects/hash-table-inl.h"
|
2019-05-23 08:51:46 +00:00
|
|
|
#include "src/objects/objects-inl.h"
|
|
|
|
#include "src/objects/objects.h"
|
2017-04-21 17:31:29 +00:00
|
|
|
#include "test/unittests/test-utils.h"
|
2016-12-19 12:50:30 +00:00
|
|
|
|
|
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
|
2017-11-22 18:04:36 +00:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
bool IsInStringInstanceTypeList(InstanceType instance_type) {
|
|
|
|
switch (instance_type) {
|
2018-02-15 19:38:09 +00:00
|
|
|
#define ASSERT_INSTANCE_TYPE(type, ...) \
|
|
|
|
STATIC_ASSERT(InstanceType::type < InstanceType::FIRST_NONSTRING_TYPE);
|
|
|
|
STRING_TYPE_LIST(ASSERT_INSTANCE_TYPE)
|
|
|
|
#undef ASSERT_INSTANCE_TYPE
|
|
|
|
#define TEST_INSTANCE_TYPE(type, ...) case InstanceType::type:
|
2017-11-22 18:04:36 +00:00
|
|
|
STRING_TYPE_LIST(TEST_INSTANCE_TYPE)
|
|
|
|
#undef TEST_INSTANCE_TYPE
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
EXPECT_LE(InstanceType::FIRST_NONSTRING_TYPE, instance_type);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CheckOneInstanceType(InstanceType instance_type) {
|
|
|
|
if (IsInStringInstanceTypeList(instance_type)) {
|
|
|
|
EXPECT_TRUE((instance_type & kIsNotStringMask) == kStringTag)
|
|
|
|
<< "Failing IsString mask check for " << instance_type;
|
|
|
|
} else {
|
|
|
|
EXPECT_FALSE((instance_type & kIsNotStringMask) == kStringTag)
|
|
|
|
<< "Failing !IsString mask check for " << instance_type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
TEST(Object, InstanceTypeList) {
|
|
|
|
#define TEST_INSTANCE_TYPE(type) CheckOneInstanceType(InstanceType::type);
|
|
|
|
|
|
|
|
INSTANCE_TYPE_LIST(TEST_INSTANCE_TYPE)
|
|
|
|
#undef TEST_INSTANCE_TYPE
|
|
|
|
}
|
|
|
|
|
2016-12-19 12:50:30 +00:00
|
|
|
TEST(Object, InstanceTypeListOrder) {
|
|
|
|
int current = 0;
|
|
|
|
int last = -1;
|
|
|
|
InstanceType current_type = static_cast<InstanceType>(current);
|
|
|
|
EXPECT_EQ(current_type, InstanceType::FIRST_TYPE);
|
|
|
|
EXPECT_EQ(current_type, InstanceType::INTERNALIZED_STRING_TYPE);
|
|
|
|
#define TEST_INSTANCE_TYPE(type) \
|
|
|
|
current_type = InstanceType::type; \
|
|
|
|
current = static_cast<int>(current_type); \
|
|
|
|
if (current > static_cast<int>(LAST_NAME_TYPE)) { \
|
2017-12-19 13:21:23 +00:00
|
|
|
EXPECT_LE(last + 1, current); \
|
2016-12-19 12:50:30 +00:00
|
|
|
} \
|
|
|
|
EXPECT_LT(last, current) << " INSTANCE_TYPE_LIST is not ordered: " \
|
|
|
|
<< "last = " << static_cast<InstanceType>(last) \
|
|
|
|
<< " vs. current = " << current_type; \
|
|
|
|
last = current;
|
|
|
|
|
|
|
|
INSTANCE_TYPE_LIST(TEST_INSTANCE_TYPE)
|
|
|
|
#undef TEST_INSTANCE_TYPE
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(Object, StructListOrder) {
|
2017-12-19 13:21:23 +00:00
|
|
|
int current = static_cast<int>(InstanceType::ACCESS_CHECK_INFO_TYPE);
|
2016-12-19 12:50:30 +00:00
|
|
|
int last = current - 1;
|
|
|
|
ASSERT_LT(0, last);
|
|
|
|
InstanceType current_type = static_cast<InstanceType>(current);
|
2018-09-21 15:22:38 +00:00
|
|
|
#define TEST_STRUCT(TYPE, class, name) \
|
|
|
|
current_type = InstanceType::TYPE; \
|
2016-12-19 12:50:30 +00:00
|
|
|
current = static_cast<int>(current_type); \
|
|
|
|
EXPECT_EQ(last + 1, current) \
|
|
|
|
<< " STRUCT_LIST is not ordered: " \
|
|
|
|
<< " last = " << static_cast<InstanceType>(last) \
|
|
|
|
<< " vs. current = " << current_type; \
|
|
|
|
last = current;
|
|
|
|
|
|
|
|
STRUCT_LIST(TEST_STRUCT)
|
|
|
|
#undef TEST_STRUCT
|
|
|
|
}
|
|
|
|
|
2019-05-27 11:31:49 +00:00
|
|
|
using ObjectWithIsolate = TestWithIsolate;
|
2017-04-21 17:31:29 +00:00
|
|
|
|
|
|
|
TEST_F(ObjectWithIsolate, DictionaryGrowth) {
|
2017-11-07 09:35:59 +00:00
|
|
|
Handle<NumberDictionary> dict = NumberDictionary::New(isolate(), 1);
|
2017-04-21 17:31:29 +00:00
|
|
|
Handle<Object> value = isolate()->factory()->null_value();
|
|
|
|
PropertyDetails details = PropertyDetails::Empty();
|
|
|
|
|
|
|
|
// This test documents the expected growth behavior of a dictionary getting
|
|
|
|
// elements added to it one by one.
|
|
|
|
STATIC_ASSERT(HashTableBase::kMinCapacity == 4);
|
|
|
|
uint32_t i = 1;
|
|
|
|
// 3 elements fit into the initial capacity.
|
|
|
|
for (; i <= 3; i++) {
|
2018-07-13 09:32:35 +00:00
|
|
|
dict = NumberDictionary::Add(isolate(), dict, i, value, details);
|
2017-04-21 17:31:29 +00:00
|
|
|
CHECK_EQ(4, dict->Capacity());
|
|
|
|
}
|
|
|
|
// 4th element triggers growth.
|
|
|
|
DCHECK_EQ(4, i);
|
|
|
|
for (; i <= 5; i++) {
|
2018-07-13 09:32:35 +00:00
|
|
|
dict = NumberDictionary::Add(isolate(), dict, i, value, details);
|
2017-04-21 17:31:29 +00:00
|
|
|
CHECK_EQ(8, dict->Capacity());
|
|
|
|
}
|
|
|
|
// 6th element triggers growth.
|
|
|
|
DCHECK_EQ(6, i);
|
|
|
|
for (; i <= 11; i++) {
|
2018-07-13 09:32:35 +00:00
|
|
|
dict = NumberDictionary::Add(isolate(), dict, i, value, details);
|
2017-04-21 17:31:29 +00:00
|
|
|
CHECK_EQ(16, dict->Capacity());
|
|
|
|
}
|
|
|
|
// 12th element triggers growth.
|
|
|
|
DCHECK_EQ(12, i);
|
|
|
|
for (; i <= 21; i++) {
|
2018-07-13 09:32:35 +00:00
|
|
|
dict = NumberDictionary::Add(isolate(), dict, i, value, details);
|
2017-04-21 17:31:29 +00:00
|
|
|
CHECK_EQ(32, dict->Capacity());
|
|
|
|
}
|
|
|
|
// 22nd element triggers growth.
|
|
|
|
DCHECK_EQ(22, i);
|
|
|
|
for (; i <= 43; i++) {
|
2018-07-13 09:32:35 +00:00
|
|
|
dict = NumberDictionary::Add(isolate(), dict, i, value, details);
|
2017-04-21 17:31:29 +00:00
|
|
|
CHECK_EQ(64, dict->Capacity());
|
|
|
|
}
|
|
|
|
// 44th element triggers growth.
|
|
|
|
DCHECK_EQ(44, i);
|
|
|
|
for (; i <= 50; i++) {
|
2018-07-13 09:32:35 +00:00
|
|
|
dict = NumberDictionary::Add(isolate(), dict, i, value, details);
|
2017-04-21 17:31:29 +00:00
|
|
|
CHECK_EQ(128, dict->Capacity());
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we grow by larger chunks, the next (sufficiently big) power of 2 is
|
|
|
|
// chosen as the capacity.
|
2017-11-07 09:35:59 +00:00
|
|
|
dict = NumberDictionary::New(isolate(), 1);
|
2018-07-12 11:04:18 +00:00
|
|
|
dict = NumberDictionary::EnsureCapacity(isolate(), dict, 65);
|
2017-04-21 17:31:29 +00:00
|
|
|
CHECK_EQ(128, dict->Capacity());
|
|
|
|
|
2017-11-07 09:35:59 +00:00
|
|
|
dict = NumberDictionary::New(isolate(), 1);
|
2018-07-12 11:04:18 +00:00
|
|
|
dict = NumberDictionary::EnsureCapacity(isolate(), dict, 30);
|
2017-04-21 17:31:29 +00:00
|
|
|
CHECK_EQ(64, dict->Capacity());
|
|
|
|
}
|
|
|
|
|
2018-04-25 09:52:59 +00:00
|
|
|
TEST_F(TestWithNativeContext, EmptyFunctionScopeInfo) {
|
|
|
|
// Check that the empty_function has a properly set up ScopeInfo.
|
|
|
|
Handle<JSFunction> function = RunJS<JSFunction>("(function(){})");
|
|
|
|
|
2018-06-23 09:05:50 +00:00
|
|
|
Handle<ScopeInfo> scope_info(function->shared().scope_info(),
|
|
|
|
function->GetIsolate());
|
2018-04-25 09:52:59 +00:00
|
|
|
Handle<ScopeInfo> empty_function_scope_info(
|
2018-06-23 09:05:50 +00:00
|
|
|
isolate()->empty_function()->shared().scope_info(),
|
|
|
|
function->GetIsolate());
|
2018-04-25 09:52:59 +00:00
|
|
|
|
|
|
|
EXPECT_EQ(scope_info->length(), empty_function_scope_info->length());
|
|
|
|
EXPECT_EQ(scope_info->Flags(), empty_function_scope_info->Flags());
|
|
|
|
EXPECT_EQ(scope_info->ParameterCount(),
|
|
|
|
empty_function_scope_info->ParameterCount());
|
|
|
|
EXPECT_EQ(scope_info->ContextLocalCount(),
|
|
|
|
empty_function_scope_info->ContextLocalCount());
|
|
|
|
}
|
|
|
|
|
2016-12-19 12:50:30 +00:00
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|