Revision: 21244
Author:   [email protected]
Date:     Fri May  9 18:22:28 2014 UTC
Log: Object.observe: avoid accessing acceptList properties more than once

BUG=v8:3315
LOG=Y
[email protected]

Review URL: https://codereview.chromium.org/270763003
http://code.google.com/p/v8/source/detail?r=21244

Added:
 /branches/bleeding_edge/test/mjsunit/regress/regress-3315.js
Modified:
 /branches/bleeding_edge/src/object-observe.js
 /branches/bleeding_edge/src/runtime.cc

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/regress/regress-3315.js Fri May 9 18:22:28 2014 UTC
@@ -0,0 +1,26 @@
+// Copyright 2014 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.
+
+var indexZeroCallCount = 0;
+var indexOneCallCount = 0;
+var lengthCallCount = 0;
+var acceptList = {
+  get 0() {
+    indexZeroCallCount++;
+    return 'foo';
+  },
+  get 1() {
+    indexOneCallCount++;
+    return 'bar';
+  },
+  get length() {
+    lengthCallCount++;
+    return 1;
+  }
+};
+
+Object.observe({}, function(){}, acceptList);
+assertEquals(1, lengthCallCount);
+assertEquals(1, indexZeroCallCount);
+assertEquals(0, indexOneCallCount);
=======================================
--- /branches/bleeding_edge/src/object-observe.js Fri May 2 21:29:15 2014 UTC +++ /branches/bleeding_edge/src/object-observe.js Fri May 9 18:22:28 2014 UTC
@@ -127,9 +127,9 @@
   typeMap[type]--;
 }

-function TypeMapCreateFromList(typeList) {
+function TypeMapCreateFromList(typeList, length) {
   var typeMap = TypeMapCreate();
-  for (var i = 0; i < typeList.length; i++) {
+  for (var i = 0; i < length; i++) {
     TypeMapAddType(typeMap, typeList[i], true);
   }
   return typeMap;
@@ -151,14 +151,17 @@
   return true;
 }

-var defaultAcceptTypes = TypeMapCreateFromList([
-  'add',
-  'update',
-  'delete',
-  'setPrototype',
-  'reconfigure',
-  'preventExtensions'
-]);
+var defaultAcceptTypes = (function() {
+  var defaultTypes = [
+    'add',
+    'update',
+    'delete',
+    'setPrototype',
+    'reconfigure',
+    'preventExtensions'
+  ];
+  return TypeMapCreateFromList(defaultTypes, defaultTypes.length);
+})();

 // An Observer is a registration to observe an object by a callback with
 // a given set of accept types. If the set of accept types is the default
@@ -170,7 +173,7 @@
     return callback;
   var observer = nullProtoObject();
   observer.callback = callback;
-  observer.accept = TypeMapCreateFromList(acceptList);
+  observer.accept = acceptList;
   return observer;
 }

@@ -306,16 +309,18 @@
   return objectInfo.performingCount > 0 ? objectInfo.performing : null;
 }

-function AcceptArgIsValid(arg) {
+function ConvertAcceptListToTypeMap(arg) {
+  // We use undefined as a sentinel for the default accept list.
   if (IS_UNDEFINED(arg))
-    return true;
+    return arg;
+
+  if (!IS_SPEC_OBJECT(arg))
+    throw MakeTypeError("observe_accept_invalid");

-  if (!IS_SPEC_OBJECT(arg) ||
-      !IS_NUMBER(arg.length) ||
-      arg.length < 0)
-    return false;
+  var len = ToInteger(arg.length);
+  if (len < 0) len = 0;

-  return true;
+  return TypeMapCreateFromList(arg, len);
 }

// CallbackInfo's optimized state is just a number which represents its global
@@ -362,15 +367,14 @@
     throw MakeTypeError("observe_non_function", ["observe"]);
   if (ObjectIsFrozen(callback))
     throw MakeTypeError("observe_callback_frozen");
-  if (!AcceptArgIsValid(acceptList))
-    throw MakeTypeError("observe_accept_invalid");

   return %ObjectObserveInObjectContext(object, callback, acceptList);
 }

 function NativeObjectObserve(object, callback, acceptList) {
   var objectInfo = ObjectInfoGetOrCreate(object);
-  ObjectInfoAddObserver(objectInfo, callback, acceptList);
+  var typeList = ConvertAcceptListToTypeMap(acceptList);
+  ObjectInfoAddObserver(objectInfo, callback, typeList);
   return object;
 }

=======================================
--- /branches/bleeding_edge/src/runtime.cc      Fri May  9 17:59:15 2014 UTC
+++ /branches/bleeding_edge/src/runtime.cc      Fri May  9 18:22:28 2014 UTC
@@ -14952,7 +14952,6 @@
   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callback, 1);
   CONVERT_ARG_HANDLE_CHECKED(Object, accept, 2);
-  RUNTIME_ASSERT(accept->IsUndefined() || accept->IsJSObject());

   Handle<Context> context(object->GetCreationContext(), isolate);
   Handle<JSFunction> function(context->native_object_observe(), isolate);

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to