From 4c85efb597793b6329dbdee5e743e7b6e8404c71 Mon Sep 17 00:00:00 2001 From: "mstarzinger@chromium.org" Date: Tue, 17 Sep 2013 11:34:20 +0000 Subject: [PATCH] Handlify JSReceiver::HasProperty and friends. R=yangguo@chromium.org Review URL: https://codereview.chromium.org/23496058 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16762 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/api.cc | 8 +++---- src/objects-inl.h | 42 ++++++++++++++++++++---------------- src/objects.cc | 26 ++++++++++------------- src/objects.h | 22 +++++++++---------- src/runtime.cc | 37 +++++++++++++++++--------------- test/cctest/test-heap.cc | 46 ++++++++++++++++++---------------------- test/cctest/test-mark-compact.cc | 4 ++-- 7 files changed, 93 insertions(+), 92 deletions(-) diff --git a/src/api.cc b/src/api.cc index 5b41f92..45c9f04 100644 --- a/src/api.cc +++ b/src/api.cc @@ -2056,7 +2056,7 @@ v8::Local v8::TryCatch::StackTrace() const { i::HandleScope scope(isolate_); i::Handle obj(i::JSObject::cast(raw_obj), isolate_); i::Handle name = isolate_->factory()->stack_string(); - if (!obj->HasProperty(*name)) return v8::Local(); + if (!i::JSReceiver::HasProperty(obj, name)) return v8::Local(); i::Handle value = i::GetProperty(isolate_, obj, name); if (value.is_null()) return v8::Local(); return v8::Utils::ToLocal(scope.CloseAndEscape(value)); @@ -3625,7 +3625,7 @@ bool v8::Object::Has(uint32_t index) { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ON_BAILOUT(isolate, "v8::Object::HasProperty()", return false); i::Handle self = Utils::OpenHandle(this); - return self->HasElement(index); + return i::JSReceiver::HasElement(self, index); } @@ -3679,8 +3679,8 @@ bool v8::Object::HasOwnProperty(Handle key) { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ON_BAILOUT(isolate, "v8::Object::HasOwnProperty()", return false); - return Utils::OpenHandle(this)->HasLocalProperty( - *Utils::OpenHandle(*key)); + return i::JSReceiver::HasLocalProperty( + Utils::OpenHandle(this), Utils::OpenHandle(*key)); } diff --git a/src/objects-inl.h b/src/objects-inl.h index 08ef1cf..56fde30 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -5714,19 +5714,23 @@ Object* JSReceiver::GetConstructor() { } -bool JSReceiver::HasProperty(Name* name) { - if (IsJSProxy()) { - return JSProxy::cast(this)->HasPropertyWithHandler(name); +bool JSReceiver::HasProperty(Handle object, + Handle name) { + if (object->IsJSProxy()) { + Handle proxy = Handle::cast(object); + return JSProxy::HasPropertyWithHandler(proxy, name); } - return GetPropertyAttribute(name) != ABSENT; + return object->GetPropertyAttribute(*name) != ABSENT; } -bool JSReceiver::HasLocalProperty(Name* name) { - if (IsJSProxy()) { - return JSProxy::cast(this)->HasPropertyWithHandler(name); +bool JSReceiver::HasLocalProperty(Handle object, + Handle name) { + if (object->IsJSProxy()) { + Handle proxy = Handle::cast(object); + return JSProxy::HasPropertyWithHandler(proxy, name); } - return GetLocalPropertyAttribute(name) != ABSENT; + return object->GetLocalPropertyAttribute(*name) != ABSENT; } @@ -5768,21 +5772,23 @@ MaybeObject* JSReceiver::GetIdentityHash(CreationFlag flag) { } -bool JSReceiver::HasElement(uint32_t index) { - if (IsJSProxy()) { - return JSProxy::cast(this)->HasElementWithHandler(index); +bool JSReceiver::HasElement(Handle object, uint32_t index) { + if (object->IsJSProxy()) { + Handle proxy = Handle::cast(object); + return JSProxy::HasElementWithHandler(proxy, index); } - return JSObject::cast(this)->GetElementAttributeWithReceiver( - this, index, true) != ABSENT; + return Handle::cast(object)->GetElementAttributeWithReceiver( + *object, index, true) != ABSENT; } -bool JSReceiver::HasLocalElement(uint32_t index) { - if (IsJSProxy()) { - return JSProxy::cast(this)->HasElementWithHandler(index); +bool JSReceiver::HasLocalElement(Handle object, uint32_t index) { + if (object->IsJSProxy()) { + Handle proxy = Handle::cast(object); + return JSProxy::HasElementWithHandler(proxy, index); } - return JSObject::cast(this)->GetElementAttributeWithReceiver( - this, index, false) != ABSENT; + return Handle::cast(object)->GetElementAttributeWithReceiver( + *object, index, false) != ABSENT; } diff --git a/src/objects.cc b/src/objects.cc index ae726fd..316b583 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -460,11 +460,10 @@ Handle JSProxy::SetElementWithHandler(Handle proxy, } -bool JSProxy::HasElementWithHandler(uint32_t index) { - String* name; - MaybeObject* maybe = GetHeap()->Uint32ToString(index); - if (!maybe->To(&name)) return maybe; - return HasPropertyWithHandler(name); +bool JSProxy::HasElementWithHandler(Handle proxy, uint32_t index) { + Isolate* isolate = proxy->GetIsolate(); + Handle name = isolate->factory()->Uint32ToString(index); + return HasPropertyWithHandler(proxy, name); } @@ -3440,17 +3439,14 @@ Handle JSReceiver::SetProperty(Handle object, } -bool JSProxy::HasPropertyWithHandler(Name* name_raw) { - Isolate* isolate = GetIsolate(); - HandleScope scope(isolate); - Handle receiver(this, isolate); - Handle name(name_raw, isolate); +bool JSProxy::HasPropertyWithHandler(Handle proxy, Handle name) { + Isolate* isolate = proxy->GetIsolate(); // TODO(rossberg): adjust once there is a story for symbols vs proxies. if (name->IsSymbol()) return false; Handle args[] = { name }; - Handle result = CallTrap( + Handle result = proxy->CallTrap( "has", isolate->derived_has_trap(), ARRAY_SIZE(args), args); if (isolate->has_pending_exception()) return false; @@ -5124,7 +5120,7 @@ Handle JSObject::DeleteElement(Handle object, Handle old_value; bool should_enqueue_change_record = false; if (FLAG_harmony_observation && object->map()->is_observed()) { - should_enqueue_change_record = object->HasLocalElement(index); + should_enqueue_change_record = HasLocalElement(object, index); if (should_enqueue_change_record) { old_value = object->GetLocalElementAccessorPair(index) != NULL ? Handle::cast(factory->the_hole_value()) @@ -5140,7 +5136,7 @@ Handle JSObject::DeleteElement(Handle object, result = AccessorDelete(object, index, mode); } - if (should_enqueue_change_record && !object->HasLocalElement(index)) { + if (should_enqueue_change_record && !HasLocalElement(object, index)) { Handle name = factory->Uint32ToString(index); EnqueueChangeRecord(object, "deleted", name, old_value); } @@ -5215,7 +5211,7 @@ Handle JSObject::DeleteProperty(Handle object, result = DeleteNormalizedProperty(object, name, mode); } - if (is_observed && !object->HasLocalProperty(*name)) { + if (is_observed && !HasLocalProperty(object, name)) { EnqueueChangeRecord(object, "deleted", name, old_value); } @@ -6166,7 +6162,7 @@ void JSObject::DefineAccessor(Handle object, bool preexists = false; if (is_observed) { if (is_element) { - preexists = object->HasLocalElement(index); + preexists = HasLocalElement(object, index); if (preexists && object->GetLocalElementAccessorPair(index) == NULL) { old_value = Object::GetElement(isolate, object, index); } diff --git a/src/objects.h b/src/objects.h index dffc46d..46d65b1 100644 --- a/src/objects.h +++ b/src/objects.h @@ -1950,7 +1950,7 @@ class JSReceiver: public HeapObject { // Casting. static inline JSReceiver* cast(Object* obj); - // Implementation of [[Put]], see ECMA-262 5th edition, section 8.12.5. + // Implementation of [[Put]], ECMA-262 5th edition, section 8.12.5. static Handle SetProperty(Handle object, Handle key, Handle value, @@ -1967,7 +1967,13 @@ class JSReceiver: public HeapObject { MUST_USE_RESULT MaybeObject* SetPropertyWithDefinedSetter(JSReceiver* setter, Object* value); - // Implementation of [[Delete]], see ECMA-262 5th edition, section 8.12.7. + // Implementation of [[HasProperty]], ECMA-262 5th edition, section 8.12.6. + static inline bool HasProperty(Handle object, Handle name); + static inline bool HasLocalProperty(Handle, Handle name); + static inline bool HasElement(Handle object, uint32_t index); + static inline bool HasLocalElement(Handle object, uint32_t index); + + // Implementation of [[Delete]], ECMA-262 5th edition, section 8.12.7. static Handle DeleteProperty(Handle object, Handle name, DeleteMode mode = NORMAL_DELETION); @@ -1993,12 +1999,6 @@ class JSReceiver: public HeapObject { inline PropertyAttributes GetElementAttribute(uint32_t index); inline PropertyAttributes GetLocalElementAttribute(uint32_t index); - // Can cause a GC. - inline bool HasProperty(Name* name); - inline bool HasLocalProperty(Name* name); - inline bool HasElement(uint32_t index); - inline bool HasLocalElement(uint32_t index); - // Return the object's prototype (might be Heap::null_value()). inline Object* GetPrototype(); @@ -9077,9 +9077,6 @@ class JSProxy: public JSReceiver { // Casting. static inline JSProxy* cast(Object* obj); - bool HasPropertyWithHandler(Name* name); - bool HasElementWithHandler(uint32_t index); - MUST_USE_RESULT MaybeObject* GetPropertyWithHandler( Object* receiver, Name* name); @@ -9154,6 +9151,9 @@ class JSProxy: public JSReceiver { Handle value, StrictModeFlag strict_mode); + static bool HasPropertyWithHandler(Handle proxy, Handle name); + static bool HasElementWithHandler(Handle proxy, uint32_t index); + static Handle DeletePropertyWithHandler(Handle proxy, Handle name, DeleteMode mode); diff --git a/src/runtime.cc b/src/runtime.cc index 238157f..7c240e2 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -2169,7 +2169,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) { // Declare the property by setting it to the initial value if provided, // or undefined, and use the correct mode (e.g. READ_ONLY attribute for // constant declarations). - ASSERT(!object->HasLocalProperty(*name)); + ASSERT(!JSReceiver::HasLocalProperty(object, name)); Handle value(isolate->heap()->undefined_value(), isolate); if (*initial_value != NULL) value = initial_value; // Declaring a const context slot is a conflicting declaration if @@ -4787,7 +4787,7 @@ MaybeObject* Runtime::HasObjectProperty(Isolate* isolate, // Check if the given key is an array index. uint32_t index; if (key->ToArrayIndex(&index)) { - return isolate->heap()->ToBoolean(object->HasElement(index)); + return isolate->heap()->ToBoolean(JSReceiver::HasElement(object, index)); } // Convert the key to a name - possibly by calling back into JavaScript. @@ -4802,7 +4802,7 @@ MaybeObject* Runtime::HasObjectProperty(Isolate* isolate, name = Handle::cast(converted); } - return isolate->heap()->ToBoolean(object->HasProperty(*name)); + return isolate->heap()->ToBoolean(JSReceiver::HasProperty(object, name)); } MaybeObject* Runtime::GetObjectPropertyOrFail( @@ -5520,7 +5520,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteProperty) { static MaybeObject* HasLocalPropertyImplementation(Isolate* isolate, Handle object, Handle key) { - if (object->HasLocalProperty(*key)) return isolate->heap()->true_value(); + if (JSReceiver::HasLocalProperty(object, key)) { + return isolate->heap()->true_value(); + } // Handle hidden prototypes. If there's a hidden prototype above this thing // then we have to check it for properties, because they are supposed to // look like they are on this object. @@ -5580,12 +5582,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) { RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) { - SealHandleScope shs(isolate); + HandleScope scope(isolate); ASSERT(args.length() == 2); - CONVERT_ARG_CHECKED(JSReceiver, receiver, 0); - CONVERT_ARG_CHECKED(Name, key, 1); + CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0); + CONVERT_ARG_HANDLE_CHECKED(Name, key, 1); - bool result = receiver->HasProperty(key); + bool result = JSReceiver::HasProperty(receiver, key); RETURN_IF_SCHEDULED_EXCEPTION(isolate); if (isolate->has_pending_exception()) return Failure::Exception(); return isolate->heap()->ToBoolean(result); @@ -5593,12 +5595,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) { RUNTIME_FUNCTION(MaybeObject*, Runtime_HasElement) { - SealHandleScope shs(isolate); + HandleScope scope(isolate); ASSERT(args.length() == 2); - CONVERT_ARG_CHECKED(JSReceiver, receiver, 0); + CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0); CONVERT_SMI_ARG_CHECKED(index, 1); - bool result = receiver->HasElement(index); + bool result = JSReceiver::HasElement(receiver, index); RETURN_IF_SCHEDULED_EXCEPTION(isolate); if (isolate->has_pending_exception()) return Failure::Exception(); return isolate->heap()->ToBoolean(result); @@ -9209,7 +9211,7 @@ static ObjectPair LoadContextSlotHelper(Arguments args, // property from it. if (!holder.is_null()) { Handle object = Handle::cast(holder); - ASSERT(object->IsJSProxy() || object->HasProperty(*name)); + ASSERT(object->IsJSProxy() || JSReceiver::HasProperty(object, name)); // GetProperty below can cause GC. Handle receiver_handle( object->IsGlobalObject() @@ -10190,7 +10192,7 @@ static bool IterateElements(Isolate* isolate, Handle element_value(elements->get(j), isolate); if (!element_value->IsTheHole()) { visitor->visit(j, element_value); - } else if (receiver->HasElement(j)) { + } else if (JSReceiver::HasElement(receiver, j)) { // Call GetElement on receiver, not its prototype, or getters won't // have the correct receiver. element_value = Object::GetElement(isolate, receiver, j); @@ -10215,7 +10217,7 @@ static bool IterateElements(Isolate* isolate, Handle element_value = isolate->factory()->NewNumber(double_value); visitor->visit(j, element_value); - } else if (receiver->HasElement(j)) { + } else if (JSReceiver::HasElement(receiver, j)) { // Call GetElement on receiver, not its prototype, or getters won't // have the correct receiver. Handle element_value = @@ -11531,7 +11533,7 @@ static bool SetLocalVariableValue(Isolate* isolate, !function_context->IsNativeContext()) { Handle ext(JSObject::cast(function_context->extension())); - if (ext->HasProperty(*variable_name)) { + if (JSReceiver::HasProperty(ext, variable_name)) { // We don't expect this to do anything except replacing // property value. SetProperty(isolate, @@ -11619,7 +11621,7 @@ static bool SetClosureVariableValue(Isolate* isolate, // be variables introduced by eval. if (context->has_extension()) { Handle ext(JSObject::cast(context->extension())); - if (ext->HasProperty(*variable_name)) { + if (JSReceiver::HasProperty(ext, variable_name)) { // We don't expect this to do anything except replacing property value. SetProperty(isolate, ext, @@ -12662,7 +12664,8 @@ static Handle MaterializeArgumentsObject( // Do not materialize the arguments object for eval or top-level code. // Skip if "arguments" is already taken. if (!function->shared()->is_function() || - target->HasLocalProperty(isolate->heap()->arguments_string())) { + JSReceiver::HasLocalProperty(target, + isolate->factory()->arguments_string())) { return target; } diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc index be51193..e3ce37d 100644 --- a/test/cctest/test-heap.cc +++ b/test/cctest/test-heap.cc @@ -209,10 +209,9 @@ TEST(HeapObjects) { CHECK(s->IsString()); CHECK_EQ(10, s->length()); - String* object_string = String::cast(heap->Object_string()); - CHECK( - Isolate::Current()->context()->global_object()->HasLocalProperty( - object_string)); + Handle object_string = Handle::cast(factory->Object_string()); + Handle global(Isolate::Current()->context()->global_object()); + CHECK(JSReceiver::HasLocalProperty(global, object_string)); // Check ToString for oddballs CheckOddball(isolate, heap->true_value(), "true"); @@ -258,6 +257,7 @@ TEST(GarbageCollection) { // Check GC. heap->CollectGarbage(NEW_SPACE); + Handle global(Isolate::Current()->context()->global_object()); Handle name = factory->InternalizeUtf8String("theFunction"); Handle prop_name = factory->InternalizeUtf8String("theSlot"); Handle prop_namex = factory->InternalizeUtf8String("theSlotx"); @@ -273,7 +273,6 @@ TEST(GarbageCollection) { Handle initial_map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); function->set_initial_map(*initial_map); - Handle global(Isolate::Current()->context()->global_object()); JSReceiver::SetProperty(global, name, function, NONE, kNonStrictMode); // Allocate an object. Unrooted after leaving the scope. Handle obj = factory->NewJSObject(function); @@ -287,8 +286,7 @@ TEST(GarbageCollection) { heap->CollectGarbage(NEW_SPACE); // Function should be alive. - CHECK(Isolate::Current()->context()->global_object()-> - HasLocalProperty(*name)); + CHECK(JSReceiver::HasLocalProperty(global, name)); // Check function is retained. Object* func_value = Isolate::Current()->context()->global_object()-> GetProperty(*name)->ToObjectChecked(); @@ -299,7 +297,6 @@ TEST(GarbageCollection) { HandleScope inner_scope(isolate); // Allocate another object, make it reachable from global. Handle obj = factory->NewJSObject(function); - Handle global(Isolate::Current()->context()->global_object()); JSReceiver::SetProperty(global, obj_name, obj, NONE, kNonStrictMode); JSReceiver::SetProperty(obj, prop_name, twenty_three, NONE, kNonStrictMode); } @@ -307,8 +304,7 @@ TEST(GarbageCollection) { // After gc, it should survive. heap->CollectGarbage(NEW_SPACE); - CHECK(Isolate::Current()->context()->global_object()-> - HasLocalProperty(*obj_name)); + CHECK(JSReceiver::HasLocalProperty(global, obj_name)); CHECK(Isolate::Current()->context()->global_object()-> GetProperty(*obj_name)->ToObjectChecked()->IsJSObject()); Object* obj = Isolate::Current()->context()->global_object()-> @@ -660,55 +656,55 @@ TEST(ObjectProperties) { Handle two(Smi::FromInt(2), isolate); // check for empty - CHECK(!obj->HasLocalProperty(*first)); + CHECK(!JSReceiver::HasLocalProperty(obj, first)); // add first JSReceiver::SetProperty(obj, first, one, NONE, kNonStrictMode); - CHECK(obj->HasLocalProperty(*first)); + CHECK(JSReceiver::HasLocalProperty(obj, first)); // delete first JSReceiver::DeleteProperty(obj, first, JSReceiver::NORMAL_DELETION); - CHECK(!obj->HasLocalProperty(*first)); + CHECK(!JSReceiver::HasLocalProperty(obj, first)); // add first and then second JSReceiver::SetProperty(obj, first, one, NONE, kNonStrictMode); JSReceiver::SetProperty(obj, second, two, NONE, kNonStrictMode); - CHECK(obj->HasLocalProperty(*first)); - CHECK(obj->HasLocalProperty(*second)); + CHECK(JSReceiver::HasLocalProperty(obj, first)); + CHECK(JSReceiver::HasLocalProperty(obj, second)); // delete first and then second JSReceiver::DeleteProperty(obj, first, JSReceiver::NORMAL_DELETION); - CHECK(obj->HasLocalProperty(*second)); + CHECK(JSReceiver::HasLocalProperty(obj, second)); JSReceiver::DeleteProperty(obj, second, JSReceiver::NORMAL_DELETION); - CHECK(!obj->HasLocalProperty(*first)); - CHECK(!obj->HasLocalProperty(*second)); + CHECK(!JSReceiver::HasLocalProperty(obj, first)); + CHECK(!JSReceiver::HasLocalProperty(obj, second)); // add first and then second JSReceiver::SetProperty(obj, first, one, NONE, kNonStrictMode); JSReceiver::SetProperty(obj, second, two, NONE, kNonStrictMode); - CHECK(obj->HasLocalProperty(*first)); - CHECK(obj->HasLocalProperty(*second)); + CHECK(JSReceiver::HasLocalProperty(obj, first)); + CHECK(JSReceiver::HasLocalProperty(obj, second)); // delete second and then first JSReceiver::DeleteProperty(obj, second, JSReceiver::NORMAL_DELETION); - CHECK(obj->HasLocalProperty(*first)); + CHECK(JSReceiver::HasLocalProperty(obj, first)); JSReceiver::DeleteProperty(obj, first, JSReceiver::NORMAL_DELETION); - CHECK(!obj->HasLocalProperty(*first)); - CHECK(!obj->HasLocalProperty(*second)); + CHECK(!JSReceiver::HasLocalProperty(obj, first)); + CHECK(!JSReceiver::HasLocalProperty(obj, second)); // check string and internalized string match const char* string1 = "fisk"; Handle s1 = factory->NewStringFromAscii(CStrVector(string1)); JSReceiver::SetProperty(obj, s1, one, NONE, kNonStrictMode); Handle s1_string = factory->InternalizeUtf8String(string1); - CHECK(obj->HasLocalProperty(*s1_string)); + CHECK(JSReceiver::HasLocalProperty(obj, s1_string)); // check internalized string and string match const char* string2 = "fugl"; Handle s2_string = factory->InternalizeUtf8String(string2); JSReceiver::SetProperty(obj, s2_string, one, NONE, kNonStrictMode); Handle s2 = factory->NewStringFromAscii(CStrVector(string2)); - CHECK(obj->HasLocalProperty(*s2)); + CHECK(JSReceiver::HasLocalProperty(obj, s2)); } diff --git a/test/cctest/test-mark-compact.cc b/test/cctest/test-mark-compact.cc index cd38392..f6e703b 100644 --- a/test/cctest/test-mark-compact.cc +++ b/test/cctest/test-mark-compact.cc @@ -201,7 +201,7 @@ TEST(MarkCompactCollector) { func_name = String::cast( heap->InternalizeUtf8String("theFunction")->ToObjectChecked()); - CHECK(isolate->context()->global_object()->HasLocalProperty(func_name)); + CHECK(JSReceiver::HasLocalProperty(global, handle(func_name))); Object* func_value = isolate->context()->global_object()-> GetProperty(func_name)->ToObjectChecked(); CHECK(func_value->IsJSFunction()); @@ -222,7 +222,7 @@ TEST(MarkCompactCollector) { obj_name = String::cast(heap->InternalizeUtf8String("theObject")->ToObjectChecked()); - CHECK(isolate->context()->global_object()->HasLocalProperty(obj_name)); + CHECK(JSReceiver::HasLocalProperty(global, handle(obj_name))); CHECK(isolate->context()->global_object()-> GetProperty(obj_name)->ToObjectChecked()->IsJSObject()); obj = JSObject::cast(isolate->context()->global_object()-> -- 2.7.4