Reviewers: Rico,

Description:
Avoid calling inherited setters when creating object literals and their
boilerplates.

Please review this at http://codereview.chromium.org/6118001/

Affected files:
  M src/handles.h
  M src/handles.cc
  M src/heap-inl.h
  M src/objects.h
  M src/objects.cc
  M src/parser.cc
  M src/runtime.cc
  A + test/mjsunit/regress/regress-1015.js
  M test/mjsunit/regress/regress-192.js


Index: src/handles.cc
diff --git a/src/handles.cc b/src/handles.cc
index 68c61b5cdb168aae904786d229da17e49046bf98..7189772f1a8026a4d6a736d1eae877a9f981a91d 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -422,6 +422,14 @@ Handle<Object> SetElement(Handle<JSObject> object,
 }


+Handle<Object> SetOwnElement(Handle<JSObject> object,
+                             uint32_t index,
+                             Handle<Object> value) {
+ ASSERT(!(object->HasPixelElements() || object->HasExternalArrayElements()));
+  CALL_HEAP_FUNCTION(object->SetElement(index, *value, false), Object);
+}
+
+
 Handle<JSObject> Copy(Handle<JSObject> obj) {
   CALL_HEAP_FUNCTION(Heap::CopyJSObject(*obj), JSObject);
 }
Index: src/handles.h
diff --git a/src/handles.h b/src/handles.h
index 8fd25dc9ef56f6d66517fd290cd7a9e5bfa0b24a..1816db7c2a0faa009b408be4e45269dca75bfec6 100644
--- a/src/handles.h
+++ b/src/handles.h
@@ -217,9 +217,10 @@ Handle<Object> SetNormalizedProperty(Handle<JSObject> object,
 Handle<Object> ForceDeleteProperty(Handle<JSObject> object,
                                    Handle<Object> key);

-Handle<Object> IgnoreAttributesAndSetLocalProperty(Handle<JSObject> object,
-                                                   Handle<String> key,
-                                                   Handle<Object> value,
+Handle<Object> IgnoreAttributesAndSetLocalProperty(
+    Handle<JSObject> object,
+    Handle<String> key,
+    Handle<Object> value,
     PropertyAttributes attributes);

 Handle<Object> SetPropertyWithInterceptor(Handle<JSObject> object,
@@ -231,6 +232,10 @@ Handle<Object> SetElement(Handle<JSObject> object,
                           uint32_t index,
                           Handle<Object> value);

+Handle<Object> SetOwnElement(Handle<JSObject> object,
+                             uint32_t index,
+                             Handle<Object> value);
+
 Handle<Object> GetProperty(Handle<JSObject> obj,
                            const char* name);

Index: src/heap-inl.h
diff --git a/src/heap-inl.h b/src/heap-inl.h
index e7700e9cb5b05cdb42f44fcf2ffa889d3829c37c..7b91e8715a18d52294739664c8383825847e7f93 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -521,10 +521,6 @@ void Heap::SetLastScriptId(Object* last_script_id) {
   CALL_AND_RETRY(FUNCTION_CALL, return, return)


-#define CALL_HEAP_FUNCTION_INLINE(FUNCTION_CALL) \
-  CALL_AND_RETRY(FUNCTION_CALL, break, break)
-
-
 #ifdef DEBUG

 inline bool Heap::allow_allocation(bool new_state) {
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index 927194f70daf2a14fb3d7617514f6326a293aacb..c46da4a0df8fc8cf0c1c8cd98064cfe8f5bb018b 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1823,8 +1823,9 @@ void JSObject::LookupRealNamedPropertyInPrototypes(String* name,
 // We only need to deal with CALLBACKS and INTERCEPTORS
MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result,
                                                         String* name,
-                                                        Object* value) {
-  if (!result->IsProperty()) {
+                                                        Object* value,
+ bool check_prototype) {
+  if (check_prototype && !result->IsProperty()) {
     LookupCallbackSetterInPrototypes(name, result);
   }

@@ -1850,7 +1851,8 @@ MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result,
           LookupResult r;
           LookupRealNamedProperty(name, &r);
           if (r.IsProperty()) {
-            return SetPropertyWithFailedAccessCheck(&r, name, value);
+            return SetPropertyWithFailedAccessCheck(&r, name, value,
+                                                    check_prototype);
           }
           break;
         }
@@ -1891,7 +1893,7 @@ MaybeObject* JSObject::SetProperty(LookupResult* result,
   // Check access rights if needed.
   if (IsAccessCheckNeeded()
       && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) {
-    return SetPropertyWithFailedAccessCheck(result, name, value);
+    return SetPropertyWithFailedAccessCheck(result, name, value, true);
   }

   if (IsJSGlobalProxy()) {
@@ -1993,7 +1995,7 @@ MaybeObject* JSObject::IgnoreAttributesAndSetLocalProperty(
   // Check access rights if needed.
   if (IsAccessCheckNeeded()
       && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) {
-    return SetPropertyWithFailedAccessCheck(&result, name, value);
+    return SetPropertyWithFailedAccessCheck(&result, name, value, false);
   }

   if (IsJSGlobalProxy()) {
Index: src/objects.h
diff --git a/src/objects.h b/src/objects.h
index eac7f9208ed5676fec3c29bda43c87b87368c0ed..fd9ff46c3bb8da29fc6d9d035cad40c4fdc32fdf 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1341,7 +1341,8 @@ class JSObject: public HeapObject {
   MUST_USE_RESULT MaybeObject* SetPropertyWithFailedAccessCheck(
       LookupResult* result,
       String* name,
-      Object* value);
+      Object* value,
+      bool check_prototype);
   MUST_USE_RESULT MaybeObject* SetPropertyWithCallback(Object* structure,
                                                        String* name,
                                                        Object* value,
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index ddb13003af9561c5b5e9061f59cf1403693006c0..9faa7f73274165cd3d7b3c0b69ff20759d028bab 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -3660,11 +3660,9 @@ Handle<Object> JsonParser::ParseJsonObject() {
       if (value.is_null()) return Handle<Object>::null();
       uint32_t index;
       if (key->AsArrayIndex(&index)) {
-        CALL_HEAP_FUNCTION_INLINE(
-            (*json_object)->SetElement(index, *value, true));
+        SetOwnElement(json_object, index, value);
       } else {
-        CALL_HEAP_FUNCTION_INLINE(
- (*json_object)->SetPropertyPostInterceptor(*key, *value, NONE));
+        IgnoreAttributesAndSetLocalProperty(json_object, key, value, NONE);
       }
     } while (scanner_.Next() == Token::COMMA);
     if (scanner_.current_token() != Token::RBRACE) {
Index: src/runtime.cc
diff --git a/src/runtime.cc b/src/runtime.cc
index 724a4363483e0aa3a806f73cdb8a24fa8958441f..5dc6998cf8832bf7112eea4bea7ff07ef89018b7 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -330,13 +330,18 @@ static Handle<Object> CreateObjectLiteralBoilerplate(
       Handle<Object> result;
       uint32_t element_index = 0;
       if (key->IsSymbol()) {
-        // If key is a symbol it is not an array element.
-        Handle<String> name(String::cast(*key));
-        ASSERT(!name->AsArrayIndex(&element_index));
-        result = SetProperty(boilerplate, name, value, NONE);
+        if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
+          // Array index as string (uint32).
+          result = SetOwnElement(boilerplate, element_index, value);
+        } else {
+          Handle<String> name(String::cast(*key));
+          ASSERT(!name->AsArrayIndex(&element_index));
+          result = IgnoreAttributesAndSetLocalProperty(boilerplate, name,
+                                                       value, NONE);
+        }
       } else if (key->ToArrayIndex(&element_index)) {
         // Array index (uint32).
-        result = SetElement(boilerplate, element_index, value);
+        result = SetOwnElement(boilerplate, element_index, value);
       } else {
         // Non-uint32 number.
         ASSERT(key->IsNumber());
@@ -345,7 +350,8 @@ static Handle<Object> CreateObjectLiteralBoilerplate(
         Vector<char> buffer(arr, ARRAY_SIZE(arr));
         const char* str = DoubleToCString(num, buffer);
         Handle<String> name = Factory::NewStringFromAscii(CStrVector(str));
-        result = SetProperty(boilerplate, name, value, NONE);
+        result = IgnoreAttributesAndSetLocalProperty(boilerplate, name,
+                                                     value, NONE);
       }
       // If setting the property on the boilerplate throws an
       // exception, the exception is converted to an empty handle in
Index: test/mjsunit/regress/regress-1015.js
diff --git a/test/mjsunit/bugs/bug-1015.js b/test/mjsunit/regress/regress-1015.js
similarity index 100%
rename from test/mjsunit/bugs/bug-1015.js
rename to test/mjsunit/regress/regress-1015.js
Index: test/mjsunit/regress/regress-192.js
diff --git a/test/mjsunit/regress/regress-192.js b/test/mjsunit/regress/regress-192.js index 8f0978f1b6e798d9a69f1cde9c4455720dd4f4ef..a8e5e9da3305f19c0a73d319d77d388c0f0d31f1 100644
--- a/test/mjsunit/regress/regress-192.js
+++ b/test/mjsunit/regress/regress-192.js
@@ -30,9 +30,16 @@

 // See http://code.google.com/p/v8/issues/detail?id=192

+// UPDATE: This bug report is no longer valid. In ES5, creating object
+// literals MUST NOT trigger inherited accessors, but act as if creating
+// the properties using DefineOwnProperty.
+
 Object.prototype.__defineGetter__("x", function() {});
+Object.prototype.__defineSetter__("y",
+ function() { assertUnreachable("setter"); });

-// Creating this object literal will throw an exception because we are
+// Creating this object literal will *not* throw an exception because we are
 // assigning to a property that has only a getter.
-assertThrows("({ x: 42 })");
-
+var x = ({ x: 42, y: 37 });
+assertEquals(42, x.x);
+assertEquals(37, x.y);


--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to