| Index: test/cctest/test-code-stub-assembler.cc
|
| diff --git a/test/cctest/test-code-stub-assembler.cc b/test/cctest/test-code-stub-assembler.cc
|
| index 539a0fd13cdb8daf40d9b31553c2471310e6bb8c..2d9b666b6d5f16a3defef091e8ab08d1eb38a7af 100644
|
| --- a/test/cctest/test-code-stub-assembler.cc
|
| +++ b/test/cctest/test-code-stub-assembler.cc
|
| @@ -232,15 +232,15 @@ void TestNameDictionaryLookup() {
|
|
|
| Label passed(&m), failed(&m);
|
| Label if_found(&m), if_not_found(&m);
|
| - Variable var_entry(&m, MachineRepresentation::kWord32);
|
| + Variable var_name_index(&m, MachineRepresentation::kWord32);
|
|
|
| m.NameDictionaryLookup<Dictionary>(dictionary, unique_name, &if_found,
|
| - &var_entry, &if_not_found);
|
| + &var_name_index, &if_not_found);
|
| m.Bind(&if_found);
|
| m.GotoUnless(
|
| m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kFound))),
|
| &failed);
|
| - m.Branch(m.Word32Equal(m.SmiToWord32(expected_arg), var_entry.value()),
|
| + m.Branch(m.Word32Equal(m.SmiToWord32(expected_arg), var_name_index.value()),
|
| &passed, &failed);
|
|
|
| m.Bind(&if_not_found);
|
| @@ -284,10 +284,12 @@ void TestNameDictionaryLookup() {
|
|
|
| for (size_t i = 0; i < arraysize(keys); i++) {
|
| int entry = dictionary->FindEntry(keys[i]);
|
| + int name_index =
|
| + Dictionary::EntryToIndex(entry) + Dictionary::kEntryKeyIndex;
|
| CHECK_NE(Dictionary::kNotFound, entry);
|
|
|
| - Handle<Object> expected_entry(Smi::FromInt(entry), isolate);
|
| - ft.CheckTrue(dictionary, keys[i], expect_found, expected_entry);
|
| + Handle<Object> expected_name_index(Smi::FromInt(name_index), isolate);
|
| + ft.CheckTrue(dictionary, keys[i], expect_found, expected_name_index);
|
| }
|
|
|
| Handle<Name> non_existing_keys[] = {
|
| @@ -418,15 +420,46 @@ namespace {
|
|
|
| void AddProperties(Handle<JSObject> object, Handle<Name> names[],
|
| size_t count) {
|
| - Handle<Object> value(Smi::FromInt(42), object->GetIsolate());
|
| + Isolate* isolate = object->GetIsolate();
|
| for (size_t i = 0; i < count; i++) {
|
| + Handle<Object> value(Smi::FromInt(static_cast<int>(42 + i)), isolate);
|
| JSObject::AddProperty(object, names[i], value, NONE);
|
| }
|
| }
|
|
|
| +Handle<AccessorPair> CreateAccessorPair(FunctionTester* ft,
|
| + const char* getter_body,
|
| + const char* setter_body) {
|
| + Handle<AccessorPair> pair = ft->isolate->factory()->NewAccessorPair();
|
| + if (getter_body) {
|
| + pair->set_getter(*ft->NewFunction(getter_body));
|
| + }
|
| + if (setter_body) {
|
| + pair->set_setter(*ft->NewFunction(setter_body));
|
| + }
|
| + return pair;
|
| +}
|
| +
|
| +void AddProperties(Handle<JSObject> object, Handle<Name> names[],
|
| + size_t names_count, Handle<Object> values[],
|
| + size_t values_count, int seed = 0) {
|
| + Isolate* isolate = object->GetIsolate();
|
| + for (size_t i = 0; i < names_count; i++) {
|
| + Handle<Object> value = values[(seed + i) % values_count];
|
| + if (value->IsAccessorPair()) {
|
| + Handle<AccessorPair> pair = Handle<AccessorPair>::cast(value);
|
| + Handle<Object> getter(pair->getter(), isolate);
|
| + Handle<Object> setter(pair->setter(), isolate);
|
| + JSObject::DefineAccessor(object, names[i], getter, setter, NONE).Check();
|
| + } else {
|
| + JSObject::AddProperty(object, names[i], value, NONE);
|
| + }
|
| + }
|
| +}
|
| +
|
| } // namespace
|
|
|
| -TEST(TryLookupProperty) {
|
| +TEST(TryHasOwnProperty) {
|
| typedef CodeStubAssembler::Label Label;
|
| Isolate* isolate(CcTest::InitIsolateOnce());
|
|
|
| @@ -445,7 +478,7 @@ TEST(TryLookupProperty) {
|
| Node* map = m.LoadMap(object);
|
| Node* instance_type = m.LoadMapInstanceType(map);
|
|
|
| - m.TryLookupProperty(object, map, instance_type, unique_name, &if_found,
|
| + m.TryHasOwnProperty(object, map, instance_type, unique_name, &if_found,
|
| &if_not_found, &if_bailout);
|
|
|
| m.Bind(&if_found);
|
| @@ -477,6 +510,10 @@ TEST(TryLookupProperty) {
|
| Handle<Object> expect_bailout(Smi::FromInt(kBailout), isolate);
|
|
|
| Factory* factory = isolate->factory();
|
| +
|
| + Handle<Name> deleted_property_name =
|
| + factory->InternalizeUtf8String("deleted");
|
| +
|
| Handle<Name> names[] = {
|
| factory->InternalizeUtf8String("a"),
|
| factory->InternalizeUtf8String("bb"),
|
| @@ -492,25 +529,59 @@ TEST(TryLookupProperty) {
|
| std::vector<Handle<JSObject>> objects;
|
|
|
| {
|
| - Handle<JSFunction> function = factory->NewFunction(factory->empty_string());
|
| - Handle<JSObject> object = factory->NewJSObject(function);
|
| + // Fast object, no inobject properties.
|
| + int inobject_properties = 0;
|
| + Handle<Map> map = Map::Create(isolate, inobject_properties);
|
| + Handle<JSObject> object = factory->NewJSObjectFromMap(map);
|
| AddProperties(object, names, arraysize(names));
|
| CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
|
| + CHECK_EQ(inobject_properties, object->map()->GetInObjectProperties());
|
| CHECK(!object->map()->is_dictionary_map());
|
| objects.push_back(object);
|
| }
|
|
|
| {
|
| + // Fast object, all inobject properties.
|
| + int inobject_properties = arraysize(names) * 2;
|
| + Handle<Map> map = Map::Create(isolate, inobject_properties);
|
| + Handle<JSObject> object = factory->NewJSObjectFromMap(map);
|
| + AddProperties(object, names, arraysize(names));
|
| + CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
|
| + CHECK_EQ(inobject_properties, object->map()->GetInObjectProperties());
|
| + CHECK(!object->map()->is_dictionary_map());
|
| + objects.push_back(object);
|
| + }
|
| +
|
| + {
|
| + // Fast object, half inobject properties.
|
| + int inobject_properties = arraysize(names) / 2;
|
| + Handle<Map> map = Map::Create(isolate, inobject_properties);
|
| + Handle<JSObject> object = factory->NewJSObjectFromMap(map);
|
| + AddProperties(object, names, arraysize(names));
|
| + CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
|
| + CHECK_EQ(inobject_properties, object->map()->GetInObjectProperties());
|
| + CHECK(!object->map()->is_dictionary_map());
|
| + objects.push_back(object);
|
| + }
|
| +
|
| + {
|
| + // Dictionary mode object.
|
| Handle<JSFunction> function = factory->NewFunction(factory->empty_string());
|
| Handle<JSObject> object = factory->NewJSObject(function);
|
| AddProperties(object, names, arraysize(names));
|
| JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0, "test");
|
| +
|
| + JSObject::AddProperty(object, deleted_property_name, object, NONE);
|
| + CHECK(JSObject::DeleteProperty(object, deleted_property_name, SLOPPY)
|
| + .FromJust());
|
| +
|
| CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
|
| CHECK(object->map()->is_dictionary_map());
|
| objects.push_back(object);
|
| }
|
|
|
| {
|
| + // Global object.
|
| Handle<JSFunction> function = factory->NewFunction(factory->empty_string());
|
| JSFunction::EnsureHasInitialMap(function);
|
| function->initial_map()->set_instance_type(JS_GLOBAL_OBJECT_TYPE);
|
| @@ -518,6 +589,11 @@ TEST(TryLookupProperty) {
|
| function->initial_map()->set_dictionary_map(true);
|
| Handle<JSObject> object = factory->NewJSGlobalObject(function);
|
| AddProperties(object, names, arraysize(names));
|
| +
|
| + JSObject::AddProperty(object, deleted_property_name, object, NONE);
|
| + CHECK(JSObject::DeleteProperty(object, deleted_property_name, SLOPPY)
|
| + .FromJust());
|
| +
|
| CHECK_EQ(JS_GLOBAL_OBJECT_TYPE, object->map()->instance_type());
|
| CHECK(object->map()->is_dictionary_map());
|
| objects.push_back(object);
|
| @@ -535,17 +611,20 @@ TEST(TryLookupProperty) {
|
|
|
| {
|
| Handle<Name> non_existing_names[] = {
|
| + factory->NewSymbol(),
|
| factory->InternalizeUtf8String("ne_a"),
|
| factory->InternalizeUtf8String("ne_bb"),
|
| + factory->NewPrivateSymbol(),
|
| factory->InternalizeUtf8String("ne_ccc"),
|
| factory->InternalizeUtf8String("ne_dddd"),
|
| + deleted_property_name,
|
| };
|
| for (Handle<JSObject> object : objects) {
|
| for (size_t key_index = 0; key_index < arraysize(non_existing_names);
|
| key_index++) {
|
| - Handle<Name> key = non_existing_names[key_index];
|
| - CHECK(!JSReceiver::HasProperty(object, key).FromJust());
|
| - ft.CheckTrue(object, key, expect_not_found);
|
| + Handle<Name> name = non_existing_names[key_index];
|
| + CHECK(!JSReceiver::HasProperty(object, name).FromJust());
|
| + ft.CheckTrue(object, name, expect_not_found);
|
| }
|
| }
|
| }
|
| @@ -564,6 +643,215 @@ TEST(TryLookupProperty) {
|
| }
|
| }
|
|
|
| +TEST(TryGetOwnProperty) {
|
| + typedef CodeStubAssembler::Label Label;
|
| + typedef CodeStubAssembler::Variable Variable;
|
| + Isolate* isolate(CcTest::InitIsolateOnce());
|
| + Factory* factory = isolate->factory();
|
| +
|
| + const int kNumParams = 2;
|
| + CodeStubAssemblerTester m(isolate, kNumParams);
|
| +
|
| + Handle<Symbol> not_found_symbol = factory->NewSymbol();
|
| + Handle<Symbol> bailout_symbol = factory->NewSymbol();
|
| + {
|
| + Node* object = m.Parameter(0);
|
| + Node* unique_name = m.Parameter(1);
|
| + Node* context = m.Parameter(kNumParams + 2);
|
| +
|
| + Variable var_value(&m, MachineRepresentation::kTagged);
|
| + Label if_found(&m), if_not_found(&m), if_bailout(&m);
|
| +
|
| + Node* map = m.LoadMap(object);
|
| + Node* instance_type = m.LoadMapInstanceType(map);
|
| +
|
| + m.TryGetOwnProperty(context, object, object, map, instance_type,
|
| + unique_name, &if_found, &var_value, &if_not_found,
|
| + &if_bailout);
|
| +
|
| + m.Bind(&if_found);
|
| + m.Return(var_value.value());
|
| +
|
| + m.Bind(&if_not_found);
|
| + m.Return(m.HeapConstant(not_found_symbol));
|
| +
|
| + m.Bind(&if_bailout);
|
| + m.Return(m.HeapConstant(bailout_symbol));
|
| + }
|
| +
|
| + Handle<Code> code = m.GenerateCode();
|
| + FunctionTester ft(code, kNumParams);
|
| +
|
| + Handle<Name> deleted_property_name =
|
| + factory->InternalizeUtf8String("deleted");
|
| +
|
| + Handle<Name> names[] = {
|
| + factory->InternalizeUtf8String("bb"),
|
| + factory->NewSymbol(),
|
| + factory->InternalizeUtf8String("a"),
|
| + factory->InternalizeUtf8String("ccc"),
|
| + factory->InternalizeUtf8String("esajefe"),
|
| + factory->NewPrivateSymbol(),
|
| + factory->InternalizeUtf8String("eeeee"),
|
| + factory->InternalizeUtf8String("p1"),
|
| + factory->InternalizeUtf8String("acshw23e"),
|
| + factory->InternalizeUtf8String(""),
|
| + factory->InternalizeUtf8String("dddd"),
|
| + factory->NewPrivateSymbol(),
|
| + factory->InternalizeUtf8String("name"),
|
| + factory->InternalizeUtf8String("p2"),
|
| + factory->InternalizeUtf8String("p3"),
|
| + factory->InternalizeUtf8String("p4"),
|
| + factory->NewPrivateSymbol(),
|
| + };
|
| + Handle<Object> values[] = {
|
| + factory->NewFunction(factory->empty_string()),
|
| + factory->NewSymbol(),
|
| + factory->InternalizeUtf8String("a"),
|
| + CreateAccessorPair(&ft, "() => 188;", "() => 199;"),
|
| + factory->NewFunction(factory->InternalizeUtf8String("bb")),
|
| + factory->InternalizeUtf8String("ccc"),
|
| + CreateAccessorPair(&ft, "() => 88;", nullptr),
|
| + handle(Smi::FromInt(1), isolate),
|
| + factory->InternalizeUtf8String(""),
|
| + CreateAccessorPair(&ft, nullptr, "() => 99;"),
|
| + factory->NewHeapNumber(4.2),
|
| + handle(Smi::FromInt(153), isolate),
|
| + factory->NewJSObject(factory->NewFunction(factory->empty_string())),
|
| + factory->NewPrivateSymbol(),
|
| + };
|
| + STATIC_ASSERT(arraysize(values) < arraysize(names));
|
| +
|
| + base::RandomNumberGenerator rand_gen(FLAG_random_seed);
|
| +
|
| + std::vector<Handle<JSObject>> objects;
|
| +
|
| + {
|
| + // Fast object, no inobject properties.
|
| + int inobject_properties = 0;
|
| + Handle<Map> map = Map::Create(isolate, inobject_properties);
|
| + Handle<JSObject> object = factory->NewJSObjectFromMap(map);
|
| + AddProperties(object, names, arraysize(names), values, arraysize(values),
|
| + rand_gen.NextInt());
|
| + CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
|
| + CHECK_EQ(inobject_properties, object->map()->GetInObjectProperties());
|
| + CHECK(!object->map()->is_dictionary_map());
|
| + objects.push_back(object);
|
| + }
|
| +
|
| + {
|
| + // Fast object, all inobject properties.
|
| + int inobject_properties = arraysize(names) * 2;
|
| + Handle<Map> map = Map::Create(isolate, inobject_properties);
|
| + Handle<JSObject> object = factory->NewJSObjectFromMap(map);
|
| + AddProperties(object, names, arraysize(names), values, arraysize(values),
|
| + rand_gen.NextInt());
|
| + CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
|
| + CHECK_EQ(inobject_properties, object->map()->GetInObjectProperties());
|
| + CHECK(!object->map()->is_dictionary_map());
|
| + objects.push_back(object);
|
| + }
|
| +
|
| + {
|
| + // Fast object, half inobject properties.
|
| + int inobject_properties = arraysize(names) / 2;
|
| + Handle<Map> map = Map::Create(isolate, inobject_properties);
|
| + Handle<JSObject> object = factory->NewJSObjectFromMap(map);
|
| + AddProperties(object, names, arraysize(names), values, arraysize(values),
|
| + rand_gen.NextInt());
|
| + CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
|
| + CHECK_EQ(inobject_properties, object->map()->GetInObjectProperties());
|
| + CHECK(!object->map()->is_dictionary_map());
|
| + objects.push_back(object);
|
| + }
|
| +
|
| + {
|
| + // Dictionary mode object.
|
| + Handle<JSFunction> function = factory->NewFunction(factory->empty_string());
|
| + Handle<JSObject> object = factory->NewJSObject(function);
|
| + AddProperties(object, names, arraysize(names), values, arraysize(values),
|
| + rand_gen.NextInt());
|
| + JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0, "test");
|
| +
|
| + JSObject::AddProperty(object, deleted_property_name, object, NONE);
|
| + CHECK(JSObject::DeleteProperty(object, deleted_property_name, SLOPPY)
|
| + .FromJust());
|
| +
|
| + CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
|
| + CHECK(object->map()->is_dictionary_map());
|
| + objects.push_back(object);
|
| + }
|
| +
|
| + {
|
| + // Global object.
|
| + Handle<JSGlobalObject> object = isolate->global_object();
|
| + AddProperties(object, names, arraysize(names), values, arraysize(values),
|
| + rand_gen.NextInt());
|
| +
|
| + JSObject::AddProperty(object, deleted_property_name, object, NONE);
|
| + CHECK(JSObject::DeleteProperty(object, deleted_property_name, SLOPPY)
|
| + .FromJust());
|
| +
|
| + CHECK_EQ(JS_GLOBAL_OBJECT_TYPE, object->map()->instance_type());
|
| + CHECK(object->map()->is_dictionary_map());
|
| + objects.push_back(object);
|
| + }
|
| +
|
| + // TODO(ishell): test proxy and interceptors when they are supported.
|
| +
|
| + {
|
| + for (Handle<JSObject> object : objects) {
|
| + for (size_t name_index = 0; name_index < arraysize(names); name_index++) {
|
| + Handle<Name> name = names[name_index];
|
| + Handle<Object> expected_value =
|
| + JSReceiver::GetProperty(object, name).ToHandleChecked();
|
| + Handle<Object> value = ft.Call(object, name).ToHandleChecked();
|
| + CHECK(expected_value->SameValue(*value));
|
| + }
|
| + }
|
| + }
|
| +
|
| + {
|
| + Handle<Name> non_existing_names[] = {
|
| + factory->NewSymbol(),
|
| + factory->InternalizeUtf8String("ne_a"),
|
| + factory->InternalizeUtf8String("ne_bb"),
|
| + factory->NewPrivateSymbol(),
|
| + factory->InternalizeUtf8String("ne_ccc"),
|
| + factory->InternalizeUtf8String("ne_dddd"),
|
| + deleted_property_name,
|
| + };
|
| + for (Handle<JSObject> object : objects) {
|
| + for (size_t key_index = 0; key_index < arraysize(non_existing_names);
|
| + key_index++) {
|
| + Handle<Name> name = non_existing_names[key_index];
|
| + Handle<Object> expected_value =
|
| + JSReceiver::GetProperty(object, name).ToHandleChecked();
|
| + CHECK(expected_value->IsUndefined(isolate));
|
| + Handle<Object> value = ft.Call(object, name).ToHandleChecked();
|
| + CHECK_EQ(*not_found_symbol, *value);
|
| + }
|
| + }
|
| + }
|
| +
|
| + {
|
| + Handle<JSFunction> function = factory->NewFunction(factory->empty_string());
|
| + Handle<JSProxy> object = factory->NewJSProxy(function, objects[0]);
|
| + CHECK_EQ(JS_PROXY_TYPE, object->map()->instance_type());
|
| + Handle<Object> value = ft.Call(object, names[0]).ToHandleChecked();
|
| + // Proxies are not supported yet.
|
| + CHECK_EQ(*bailout_symbol, *value);
|
| + }
|
| +
|
| + {
|
| + Handle<JSObject> object = isolate->global_proxy();
|
| + CHECK_EQ(JS_GLOBAL_PROXY_TYPE, object->map()->instance_type());
|
| + // Global proxies are not supported yet.
|
| + Handle<Object> value = ft.Call(object, names[0]).ToHandleChecked();
|
| + CHECK_EQ(*bailout_symbol, *value);
|
| + }
|
| +}
|
| +
|
| namespace {
|
|
|
| void AddElement(Handle<JSObject> object, uint32_t index, Handle<Object> value,
|
| @@ -577,7 +865,7 @@ TEST(TryLookupElement) {
|
| typedef CodeStubAssembler::Label Label;
|
| Isolate* isolate(CcTest::InitIsolateOnce());
|
|
|
| - const int kNumParams = 4;
|
| + const int kNumParams = 3;
|
| CodeStubAssemblerTester m(isolate, kNumParams);
|
|
|
| enum Result { kFound, kNotFound, kBailout };
|
|
|