From: feng@chromium.org Date: Thu, 15 Jan 2009 17:39:23 +0000 (+0000) Subject: Fix issue 6264 with a test case. X-Git-Tag: upstream/4.7.83~24796 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2cb36759ba643797ee0e616e5e0a5dcae1539658;p=platform%2Fupstream%2Fv8.git Fix issue 6264 with a test case. The problem is that Disable/EnableAccessCheck on an object may chnage its constructor's behavior if object's map is the same as constructor's initial map. By copying maps, the constructor's initial map is not changed. Review URL: http://codereview.chromium.org/18067 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1087 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/runtime.cc b/src/runtime.cc index 326921770..f75aecf56 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -343,8 +343,16 @@ static Object* Runtime_GetTemplateField(Arguments args) { static Object* Runtime_DisableAccessChecks(Arguments args) { ASSERT(args.length() == 1); CONVERT_CHECKED(HeapObject, object, args[0]); - bool needs_access_checks = object->map()->is_access_check_needed(); - object->map()->set_is_access_check_needed(false); + Map* old_map = object->map(); + bool needs_access_checks = old_map->is_access_check_needed(); + if (needs_access_checks) { + // Copy map so it won't interfere constructor's initial map. + Object* new_map = old_map->CopyDropTransitions(); + if (new_map->IsFailure()) return new_map; + + Map::cast(new_map)->set_is_access_check_needed(false); + object->set_map(Map::cast(new_map)); + } return needs_access_checks ? Heap::true_value() : Heap::false_value(); } @@ -352,7 +360,15 @@ static Object* Runtime_DisableAccessChecks(Arguments args) { static Object* Runtime_EnableAccessChecks(Arguments args) { ASSERT(args.length() == 1); CONVERT_CHECKED(HeapObject, object, args[0]); - object->map()->set_is_access_check_needed(true); + Map* old_map = object->map(); + if (!old_map->is_access_check_needed()) { + // Copy map so it won't interfere constructor's initial map. + Object* new_map = old_map->CopyDropTransitions(); + if (new_map->IsFailure()) return new_map; + + Map::cast(new_map)->set_is_access_check_needed(true); + object->set_map(Map::cast(new_map)); + } return Heap::undefined_value(); } diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index 926272e84..6daa0d19e 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -5448,6 +5448,50 @@ THREADED_TEST(DisableAccessChecksWhileConfiguring) { CHECK(value->BooleanValue()); } +static bool NamedGetAccessBlocker(Local obj, + Local name, + v8::AccessType type, + Local data) { + return false; +} + + +static bool IndexedGetAccessBlocker(Local obj, + uint32_t key, + v8::AccessType type, + Local data) { + return false; +} + + + +THREADED_TEST(AccessChecksReenabledCorrectly) { + v8::HandleScope scope; + LocalContext context; + Local templ = ObjectTemplate::New(); + templ->SetAccessCheckCallbacks(NamedGetAccessBlocker, + IndexedGetAccessBlocker); + templ->Set(v8_str("a"), v8_str("a")); + // Add more than 8 (see kMaxFastProperties) properties + // so that the constructor will force copying map. + char buf[5]; + for (int i = 0; i < 999; i++) { + sprintf_s(buf, 5, "x%3d", i); + templ->Set(v8_str(buf), v8::Number::New(i)); + } + + Local instance_1 = templ->NewInstance(); + context->Global()->Set(v8_str("obj_1"), instance_1); + + Local value_1 = CompileRun("obj_1.a"); + CHECK(value_1->IsUndefined()); + + Local instance_2 = templ->NewInstance(); + context->Global()->Set(v8_str("obj_2"), instance_2); + + Local value_2 = CompileRun("obj_2.a"); + CHECK(value_2->IsUndefined()); +} // This tests that access check information remains on the global // object template when creating contexts.